![Reward Image]()
@@ -478,4 +533,68 @@ const childId = computed(() => child.value?.id ?? null)
justify-content: center;
margin: 2rem 0;
}
+
+.back-btn {
+ background: var(--back-btn-bg);
+ border: 0;
+ padding: 0.6rem 1rem;
+ border-radius: 8px;
+ cursor: pointer;
+ margin-bottom: 1.5rem;
+ color: var(--back-btn-color);
+ font-weight: 600;
+}
+
+.item-points {
+ color: var(--item-points-color, #ffd166);
+ font-size: 1rem;
+ font-weight: 900;
+ text-shadow: var(--item-points-shadow);
+}
+
+.ready {
+ color: var(--item-points-ready-color, #38c172);
+ letter-spacing: 0.5px;
+}
+.pending {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 80%;
+ background: var(--pending-block-bg, #222b);
+ color: var(--pending-block-color, #62ff7a);
+ font-weight: 700;
+ font-size: 1.05rem;
+ text-align: center;
+ border-radius: 6px;
+ padding: 0.4rem 0;
+ letter-spacing: 2px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 2;
+ opacity: 0.95;
+ pointer-events: none;
+}
+
+/* Mobile tweaks */
+@media (max-width: 480px) {
+ .item-points {
+ font-size: 0.78rem;
+ }
+}
+
+:deep(.good) {
+ border-color: var(--list-item-border-good);
+ background: var(--list-item-bg-good);
+}
+:deep(.bad) {
+ border-color: var(--list-item-border-bad);
+ background: var(--list-item-bg-bad);
+}
+:deep(.reward) {
+ border-color: var(--list-item-border-reward);
+ background: var(--list-item-bg-reward);
+}
diff --git a/web/vue-app/src/components/shared/ScrollingList.vue b/web/vue-app/src/components/shared/ScrollingList.vue
index 5af7e46..1033a5d 100644
--- a/web/vue-app/src/components/shared/ScrollingList.vue
+++ b/web/vue-app/src/components/shared/ScrollingList.vue
@@ -5,7 +5,7 @@ import { getCachedImageUrl, revokeAllImageUrls } from '@/common/imageCache'
const props = defineProps<{
title: string
fetchBaseUrl: string
- ids: readonly string[]
+ ids?: readonly string[]
itemKey: string
imageFields?: readonly string[]
isParentAuthenticated?: boolean
@@ -78,6 +78,16 @@ const fetchItems = async () => {
}
}
+async function refresh() {
+ await fetchItems()
+ loading.value = false
+}
+
+defineExpose({
+ refresh,
+ items,
+})
+
const centerItem = async (itemId: string) => {
await nextTick()
const wrapper = scrollWrapper.value
@@ -231,6 +241,7 @@ onBeforeUnmount(() => {
flex-direction: column;
align-items: center;
cursor: pointer;
+ user-select: none; /* Prevent image selection */
}
.item-card:hover {