diff --git a/.github/specs/feat-login-security.md b/.github/specs/archive/feat-login-security.md similarity index 100% rename from .github/specs/feat-login-security.md rename to .github/specs/archive/feat-login-security.md diff --git a/.github/specs/feat-landing-page.md b/.github/specs/feat-landing-page.md new file mode 100644 index 0000000..17e481b --- /dev/null +++ b/.github/specs/feat-landing-page.md @@ -0,0 +1,125 @@ +# Feature: Landing page with details + +## Overview + +When an unauthenticated user visits the web site, they will be sent to this landing page. The page will contain a hero with various images. A sign up/sign in component. On scrolling, various components will show describing the application features and functionality. + +**Goal:** New users are brought to the landing page to learn more about the app. + +**User Story:** +As a new user, I should be presented with the landing page that tells me about the app. + +**Rules:** +.github/copilot-instructions.md +You know how my app works at a high level + +**Discussions:** + +- I want each part of the landing page as different components (rows) +- Should these components go into their own directory (components/landing) + +1. Row 1 + - My logo is resources\logo\full_logo.png + - I plan to have my logo in the center near the top of the landing page + - I'd like to have my hero as resources\logo\hero.png + - I'd like to have my current sign in / sign up logic copied to a new component, but with this hero, it should be modern looking - semi-transparent glassmorphism box + - Should I have sign in or sign up? or compact both together +2. Row 2 + - This should describe the problem - getting kids to do chores consistently - Describe how a system benefits: + 1. Develops Executive Function: Managing a "to-do list" teaches kids how to prioritize tasks, manage their time, and follow multi-step directions—skills that translate directly to schoolwork and future careers. + 2. Fosters a "Can-Do" Attitude: Completing a task provides a tangible sense of mastery. This builds genuine self-esteem because it’s based on actual competence rather than just empty praise. + 3. Encourages Accountability: A system moves chores from "Mom/Dad is nagging me" to "This is my responsibility." It teaches that their actions (or lack thereof) have a direct impact on the people they live with. + 4. Normalizes Life Skills: By the time they head out on their own, "adulting" won't feel like a mountain to climb. Cooking, cleaning, and organizing will be second nature rather than a stressful learning curve. + 5. Promotes Family Belonging: Contributing to the home makes a child feel like a teammate rather than a guest. It reinforces the idea that a family is a unit where everyone supports one another. +3. Row 3 + - This should describe how my app helps to solve the problem by creating the system + 1. Chores can be created with customizable points that children have fun collecting. + 2. Customized reward offer insentives for a child to set a goal. (saving points, etc) + 3. Easy interface for children to see which chores need to be done and what rewards they can afford. + 4. Parental controls (hidden) behind a pin that offer powerful tools for managing the system + - In this component we'll show some screen shots of the interface. +4. Row 4 + - I'm not sure what else I should add for now + +- How should I handle colors - should I follow my current theme in colors.css or should I adopt my logo / hero colors? +- Should my landing page be more modern and sleek with animations? What kind? +- Considerations for mobile should also be handled (whether in portrait or landscape mode) + +- *** + +## Data Model Changes + +### Backend Model + +### Frontend Model + +--- + +## Backend Implementation + +## Backend Tests + +- [ ] + +--- + +## Frontend Implementation + +- [x] Copy `resources/logo/full_logo.png` and `hero.png` to `frontend/vue-app/public/images/` +- [x] Add landing CSS variables to `colors.css` +- [x] Create `src/components/landing/LandingPage.vue` — orchestrator with sticky nav +- [x] Create `src/components/landing/LandingHero.vue` — hero section with logo, tagline, glassmorphism CTA card +- [x] Create `src/components/landing/LandingProblem.vue` — 5-benefit problem section +- [x] Create `src/components/landing/LandingFeatures.vue` — 4-feature alternating layout with screenshot placeholders +- [x] Create `src/components/landing/LandingFooter.vue` — dark footer with links +- [x] Update router: add `/` → LandingPage route (meta: isPublic), update auth guard + +## Frontend Tests + +- [x] Update `authGuard.spec.ts`: fix redirect assertions (`/auth` → `/`) and add 3 landing-route guard tests +- [x] Create `src/components/landing/__tests__/LandingHero.spec.ts`: renders logo, tagline, buttons; CTA clicks push correct routes + +--- + +## Future Considerations + +- Eventually add a pricing section (component) + +--- + +## Acceptance Criteria (Definition of Done) + +### Backend + +- [ ] + +### Frontend + +- [x] Unauthenticated user visiting `/` sees the full landing page +- [x] Sign In CTA routes to `/auth/login` +- [x] Get Started CTA routes to `/auth/signup` +- [x] Logged-in user visiting `/` is redirected to `/child` or `/parent` +- [x] Unauthenticated user visiting any protected route is redirected to `/` (landing) +- [x] All 4 rows render: Hero, Problem, Features, Footer +- [x] Sticky nav appears on scroll +- [x] Mobile: hero buttons stack vertically, grid goes single-column +- [x] All colors use `colors.css` variables only + +--- + +## Bugs + +### BUG-001 — Landing page instantly redirects to `/auth` on first visit + +**Status:** Fixed + +**Description:** +Visiting `/` as an unauthenticated user caused a visible flash of the landing page followed by an immediate hard redirect to `/auth`, making the landing page effectively unreachable. + +**Root Cause:** +`App.vue` calls `checkAuth()` on mount, which hits `/api/auth/me`. For an unauthenticated user this returns a `401`. The fetch interceptor in `api.ts` (`handleUnauthorizedResponse`) then attempted a token refresh, which also failed, and finally called `window.location.assign('/auth')`. The interceptor only exempted paths already starting with `/auth` — not the landing page at `/`. + +**Solution:** + +- [`frontend/vue-app/src/common/api.ts`](../frontend/vue-app/src/common/api.ts) — Added `if (window.location.pathname === '/') return` inside `handleUnauthorizedResponse()` so the unauthorized interceptor does not forcibly redirect away from the public landing page. +- [`frontend/vue-app/src/stores/auth.ts`](../frontend/vue-app/src/stores/auth.ts) — Updated the cross-tab logout storage event handler to redirect to `/` instead of `/auth/login`, and skip the redirect entirely if already on `/`. diff --git a/.gitignore b/.gitignore index c921730..204f7f1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ backend/test_data/db/tasks.json backend/test_data/db/users.json logs/account_deletion.log backend/test_data/db/tracking_events.json +resources/ diff --git a/frontend/vue-app/public/images/c_logo.png b/frontend/vue-app/public/images/c_logo.png new file mode 100644 index 0000000..07dc295 Binary files /dev/null and b/frontend/vue-app/public/images/c_logo.png differ diff --git a/frontend/vue-app/public/images/chorly_logo.png b/frontend/vue-app/public/images/chorly_logo.png new file mode 100644 index 0000000..8013084 Binary files /dev/null and b/frontend/vue-app/public/images/chorly_logo.png differ diff --git a/frontend/vue-app/public/images/full_logo.png b/frontend/vue-app/public/images/full_logo.png new file mode 100644 index 0000000..2d57165 Binary files /dev/null and b/frontend/vue-app/public/images/full_logo.png differ diff --git a/frontend/vue-app/public/images/hero.png b/frontend/vue-app/public/images/hero.png new file mode 100644 index 0000000..4107fb1 Binary files /dev/null and b/frontend/vue-app/public/images/hero.png differ diff --git a/frontend/vue-app/src/assets/colors.css b/frontend/vue-app/src/assets/colors.css index 4c6393e..9495bab 100644 --- a/frontend/vue-app/src/assets/colors.css +++ b/frontend/vue-app/src/assets/colors.css @@ -183,4 +183,24 @@ --create-btn-border: #2563eb; --create-btn-hover-bg: #2563eb; --create-btn-hover-color: #fff; + + /* Landing page styles */ + --landing-overlay: rgba(0, 0, 0, 0.48); + --landing-glass-bg: rgba(255, 255, 255, 0.12); + --landing-glass-border: rgba(255, 255, 255, 0.25); + --landing-glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.28); + --landing-section-alt: #f4f6fb; + --landing-section-dark: #1a1830; + --landing-hero-text: #ffffff; + --landing-hero-subtext: rgba(255, 255, 255, 0.82); + --landing-problem-heading: #2d2a4a; + --landing-problem-body: #4a4870; + --landing-card-number: #667eea; + --landing-feature-heading: #ffffff; + --landing-feature-body: rgba(255, 255, 255, 0.88); + --landing-placeholder-bg: rgba(255, 255, 255, 0.08); + --landing-placeholder-border: rgba(255, 255, 255, 0.2); + --landing-footer-text: rgba(255, 255, 255, 0.7); + --landing-nav-bg: rgba(255, 255, 255, 0.06); + --landing-nav-border: rgba(255, 255, 255, 0.15); } diff --git a/frontend/vue-app/src/common/api.ts b/frontend/vue-app/src/common/api.ts index ecd121b..a4c3c43 100644 --- a/frontend/vue-app/src/common/api.ts +++ b/frontend/vue-app/src/common/api.ts @@ -23,6 +23,7 @@ function handleUnauthorizedResponse(): void { logoutUser() if (typeof window === 'undefined') return if (window.location.pathname.startsWith('/auth')) return + if (window.location.pathname === '/') return if (unauthorizedRedirectHandler) { unauthorizedRedirectHandler() return diff --git a/frontend/vue-app/src/components/child/ChildView.vue b/frontend/vue-app/src/components/child/ChildView.vue index 2b24966..3dd2213 100644 --- a/frontend/vue-app/src/components/child/ChildView.vue +++ b/frontend/vue-app/src/components/child/ChildView.vue @@ -577,6 +577,35 @@ onUnmounted(() => {
+ Chorly gives your family a structured, fun, and rewarding system — so chores become + something kids want to do. +
+{{ feature.body }}
+
+
+ Turn chores into achievements.
Raise kids who own their responsibilities.
+
+ Nagging doesn't work. Vague expectations don't work. But a clear, consistent system changes + everything — for your kids and for you. +
+{{ benefit.body }}
+