From cca297a4eb3cc4caf2b8cc45f538a39d4baaa80d Mon Sep 17 00:00:00 2001 From: AzuTear Date: Thu, 18 Jun 2026 06:46:41 +0200 Subject: [PATCH] Redesign public site, add phase gating and clip submission - Rebuild landing page and Nominations/Voting/Winners views in the Jayuhime brand style (purple/gold/pastel-rainbow, stars, PageHero banner) - Gate participation by season phase (nominate/clip share the nomination window, vote in the voting window); hide closed/locked pages from nav - Add login-gated clip submission flow (link-based) + voting clip links - Make candidate admin scalable: searchable, filterable, paginated table with modal create/edit and confirm-delete; add delete API/store actions - New reusable Modal and PageHero components, usePhases composable - Segmented top nav and full-size header on admin routes - vite: honor PORT env for preview Co-Authored-By: Claude Opus 4.8 --- frontend/src/assets/hero-keyvisual.svg | 131 +++ frontend/src/components/AppShell.vue | 42 +- .../src/components/admin/AdminPageHeader.vue | 45 +- frontend/src/components/ui/Modal.vue | 84 ++ frontend/src/components/ui/PageHero.vue | 59 ++ frontend/src/composables/usePhases.ts | 48 ++ frontend/src/lib/api.ts | 24 + frontend/src/router.ts | 23 + frontend/src/stores/awards.ts | 41 +- frontend/src/types/awards.ts | 11 + frontend/src/views/ClipSubmissionView.vue | 169 ++++ frontend/src/views/HomeView.vue | 797 ++++++++++++------ frontend/src/views/NominationsView.vue | 193 +++-- frontend/src/views/VotingView.vue | 164 ++-- frontend/src/views/WinnersView.vue | 67 +- .../src/views/admin/AdminCandidatesView.vue | 525 ++++++------ frontend/vite.config.ts | 3 + 17 files changed, 1735 insertions(+), 691 deletions(-) create mode 100644 frontend/src/assets/hero-keyvisual.svg create mode 100644 frontend/src/components/ui/Modal.vue create mode 100644 frontend/src/components/ui/PageHero.vue create mode 100644 frontend/src/composables/usePhases.ts create mode 100644 frontend/src/views/ClipSubmissionView.vue diff --git a/frontend/src/assets/hero-keyvisual.svg b/frontend/src/assets/hero-keyvisual.svg new file mode 100644 index 0000000..b2041cf --- /dev/null +++ b/frontend/src/assets/hero-keyvisual.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/components/AppShell.vue b/frontend/src/components/AppShell.vue index 9d63c8e..9aefcf6 100644 --- a/frontend/src/components/AppShell.vue +++ b/frontend/src/components/AppShell.vue @@ -5,9 +5,11 @@ import { Star } from '@lucide/vue' import Button from './ui/Button.vue' import { useAuthStore } from '../stores/auth' +import { usePhases } from '../composables/usePhases' const route = useRoute() const authStore = useAuthStore() +const { infoForPhaseKey } = usePhases() const loginOpen = ref(false) const loginError = ref('') const loginForm = reactive({ @@ -18,8 +20,9 @@ const loginForm = reactive({ const navItems = [ { label: 'Home', to: '/' }, - { label: 'Nominierung', to: '/nominations' }, - { label: 'Voting', to: '/voting' }, + { label: 'Nominierung', to: '/nominations', requiresAuth: true, phase: 'nomination' }, + { label: 'Voting', to: '/voting', requiresAuth: true, phase: 'voting' }, + { label: 'Clips', to: '/clips', requiresAuth: true, phase: 'nomination' }, { label: 'Gewinner', to: '/winners' }, { label: 'Admin', to: '/admin' }, ] @@ -29,9 +32,15 @@ const currentLabel = computed( ) const visibleNavItems = computed(() => - navItems.filter((item) => item.to !== '/admin' || authStore.isAdmin), + navItems.filter((item) => { + if (item.to === '/admin') return authStore.isAdmin + // Teilnahme-Seiten erst nach Login zeigen + if (item.requiresAuth && !authStore.isLoggedIn) return false + // ... und nur, solange ihre Phase aktiv ist + if (item.phase && infoForPhaseKey(item.phase).state !== 'active') return false + return true + }), ) -const isAdminRoute = computed(() => route.path.startsWith('/admin')) async function login(role: 'viewer' | 'admin') { loginError.value = '' @@ -58,20 +67,18 @@ async function login(role: 'viewer' | 'admin') {
-
+
- +
VTUBER - STAR AWARDS + STAR AWARDS
@@ -84,7 +91,10 @@ async function login(role: 'viewer' | 'admin') {
@@ -104,13 +114,15 @@ async function login(role: 'viewer' | 'admin') {
-