From 0b497157adc8bae03791642647376fc9ca06d65e Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Mon, 13 Jul 2026 08:56:23 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20landing=20ref=C4=83cut=20+=20=C3=AEnvel?= =?UTF-8?q?i=C8=99=20public=20unificat=20pentru=20login/register/book?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Landing: - hero cu un singur CTA (scoase „Vezi cum arată", „Rezervă fără cont" și nota) - „Spații deschise rezervării acum" pe poziția 2, în bandă evidențiată cu accent; listează toate proprietățile publice active (fără filtrul list_on_landing) - showcase-ul mutat în bandă neutră etichetată „Demonstrație" ca să nu se confunde cu controale reale Pagini publice: - PublicNav.vue + PublicFooter.vue extrase și refolosite de Landing, LegalPage și noul PublicShell.vue (login/register/book primesc header/footer de landing, cu cele 8 teme; tokenii --color-* remapați la paleta landing în scope-ul shell) - pe mobil: nav compact cu meniu hamburger (drawer ancorat dreapta, iconițe lucide, închidere la tap în afară/Escape); logo-ul Romfast rămâne în footer Fix-uri: - QR-ul proprietății encodează URL-ul cu slug (fallback pe id) - deep-link-urile către rutele manager/admin nu mai sar la /dashboard: guard-ul așteaptă authStore.ready înainte de verificarea rolurilor - drawer-ul nu se mai închidea singur la tap pe iconiță (listener pe pointerdown + gardă pentru target detașat după re-render) Co-Authored-By: Claude Fable 5 --- .gitignore | 3 + frontend/src/components/LegalPage.vue | 110 +-------- frontend/src/components/PublicFooter.vue | 45 ++++ frontend/src/components/PublicNav.vue | 253 +++++++++++++++++++++ frontend/src/components/PublicShell.vue | 125 +++++++++++ frontend/src/router/index.ts | 14 +- frontend/src/stores/auth.ts | 5 +- frontend/src/views/Landing.vue | 275 ++++++++--------------- frontend/src/views/Login.vue | 7 +- frontend/src/views/PropertyDetail.vue | 5 +- frontend/src/views/PublicBooking.vue | 6 +- frontend/src/views/Register.vue | 7 +- 12 files changed, 555 insertions(+), 300 deletions(-) create mode 100644 frontend/src/components/PublicFooter.vue create mode 100644 frontend/src/components/PublicNav.vue create mode 100644 frontend/src/components/PublicShell.vue diff --git a/.gitignore b/.gitignore index 12b90b4..bcd2ed5 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,6 @@ Thumbs.db # Runtime .pids .gstack/ + +# Playwright MCP artifacts +.playwright-mcp/ diff --git a/frontend/src/components/LegalPage.vue b/frontend/src/components/LegalPage.vue index 23b9617..f3922f6 100644 --- a/frontend/src/components/LegalPage.vue +++ b/frontend/src/components/LegalPage.vue @@ -2,37 +2,7 @@
- +
@@ -42,30 +12,22 @@
-
- -
+
diff --git a/frontend/src/components/PublicFooter.vue b/frontend/src/components/PublicFooter.vue new file mode 100644 index 0000000..3938808 --- /dev/null +++ b/frontend/src/components/PublicFooter.vue @@ -0,0 +1,45 @@ + + + diff --git a/frontend/src/components/PublicNav.vue b/frontend/src/components/PublicNav.vue new file mode 100644 index 0000000..9096986 --- /dev/null +++ b/frontend/src/components/PublicNav.vue @@ -0,0 +1,253 @@ + + + + + diff --git a/frontend/src/components/PublicShell.vue b/frontend/src/components/PublicShell.vue new file mode 100644 index 0000000..48543a2 --- /dev/null +++ b/frontend/src/components/PublicShell.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 5b238e4..72ba43e 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -28,13 +28,13 @@ const router = createRouter({ path: '/login', name: 'Login', component: Login, - meta: { requiresAuth: false } + meta: { requiresAuth: false, fullBleed: true } }, { path: '/register', name: 'Register', component: () => import('@/views/Register.vue'), - meta: { requiresAuth: false } + meta: { requiresAuth: false, fullBleed: true } }, { path: '/verify', @@ -46,7 +46,7 @@ const router = createRouter({ path: '/book/:slug?', name: 'PublicBooking', component: () => import('@/views/PublicBooking.vue'), - meta: { requiresAuth: false, isPublic: true } + meta: { requiresAuth: false, isPublic: true, fullBleed: true } }, { path: '/dashboard', @@ -138,9 +138,15 @@ const router = createRouter({ }) // Navigation guard -router.beforeEach((to, _from, next) => { +router.beforeEach(async (to, _from, next) => { const authStore = useAuthStore() + // On a hard page load the user is fetched asynchronously; wait for it so + // role-based checks below don't reject a deep link before the user exists. + if (authStore.token && !authStore.user) { + await authStore.ready + } + if (to.meta.isPublic) { next() } else if (to.meta.requiresAuth && !authStore.isAuthenticated) { diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts index 914f9b3..5d0a002 100644 --- a/frontend/src/stores/auth.ts +++ b/frontend/src/stores/auth.ts @@ -37,11 +37,14 @@ export const useAuthStore = defineStore('auth', () => { } } - initFromToken() + // Router guards await this so role checks don't run before the user loads + // on a hard page load (deep link to a manager/admin route). + const ready = initFromToken() return { token, user, + ready, isAuthenticated, isAdmin, isSuperadmin, diff --git a/frontend/src/views/Landing.vue b/frontend/src/views/Landing.vue index 2b4b751..9787ed7 100644 --- a/frontend/src/views/Landing.vue +++ b/frontend/src/views/Landing.vue @@ -2,36 +2,7 @@
- +
@@ -45,10 +16,7 @@

{{ ctaText }} - Vezi cum arată - Rezervă fără cont
-

Cont gratuit, gata în câteva secunde.

@@ -87,13 +55,53 @@
- -
+ +
+
+

Spații deschise rezervării acum

+ +
+ + +
+
+
+ + +
+
+
+

Vezi cum arată aplicația

+

Capturi demonstrative din ROA Space — nu sunt controale reale.

+
roa.space/dashboard + Demonstrație
-
- - -
-

Spații deschise rezervării acum

-

Alege un spațiu și rezervă fără cont, în câteva minute.

- -
- - -
+
@@ -280,17 +258,7 @@ -
- -
+ @@ -298,6 +266,8 @@