moved habits and quizzes to pet page

This commit is contained in:
masongga
2026-05-24 09:13:36 -06:00
parent e02468a9cc
commit c1b48c5e8d
10 changed files with 41 additions and 50 deletions

View File

@@ -8,8 +8,7 @@ export default function AvatarPage() {
<AppShell <AppShell
title="Your bit" title="Your bit"
description="Watch your digital self roam, breathe, and react to how you care for yourself." description="Watch your digital self roam, breathe, and react to how you care for yourself."
fillViewport wide
centered
> >
<Suspense fallback={<p className="text-sm text-muted-foreground">Loading...</p>}> <Suspense fallback={<p className="text-sm text-muted-foreground">Loading...</p>}>
<AvatarPageContent /> <AvatarPageContent />

View File

@@ -1,13 +1,7 @@
import { DailyQuizForm } from "@/components/daily-quiz/daily-quiz-form"; import { redirect } from "next/navigation";
import { AppShell } from "@/components/layout/app-shell";
import { routes } from "@/lib/routes";
export default function DailyQuizPage() { export default function DailyQuizPage() {
return ( redirect(`${routes.avatar}#bit-daily-quiz`);
<AppShell
title="Daily quiz"
description="Complete your once-per-day wellness sliders and journal."
>
<DailyQuizForm />
</AppShell>
);
} }

View File

@@ -1,13 +1,7 @@
import { HabitTracker } from "@/components/habits/habit-tracker"; import { redirect } from "next/navigation";
import { AppShell } from "@/components/layout/app-shell";
import { routes } from "@/lib/routes";
export default function HabitsPage() { export default function HabitsPage() {
return ( redirect(`${routes.avatar}#bit-daily-tasks`);
<AppShell
title="Habits"
description="Complete today's tasks and manage your habit list."
>
<HabitTracker mode="all" />
</AppShell>
);
} }

View File

@@ -147,6 +147,15 @@
@apply flex min-h-0 w-full flex-1 flex-col items-center justify-center; @apply flex min-h-0 w-full flex-1 flex-col items-center justify-center;
} }
/* Bit home: same pet stage height as fillViewport layout (header + main padding accounted for). */
.bit-home-pet-stage {
@apply pet-viewport-stage flex w-full flex-col items-center justify-center;
min-height: calc(
100dvh - var(--app-topbar-height) - var(--app-nav-offset) -
env(safe-area-inset-top, 0px) - 11rem
);
}
.tamagotchi-shell-fill { .tamagotchi-shell-fill {
@apply flex min-h-0 w-full max-w-4xl flex-1 flex-col; @apply flex min-h-0 w-full max-w-4xl flex-1 flex-col;
} }

View File

@@ -2,6 +2,8 @@
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { DailyQuizForm } from "@/components/daily-quiz/daily-quiz-form";
import { HabitTracker } from "@/components/habits/habit-tracker";
import { PetHabitat } from "@/components/pet/pet-habitat"; import { PetHabitat } from "@/components/pet/pet-habitat";
import { HABIT_PET_DATA_UPDATED_EVENT } from "@/lib/app-events"; import { HABIT_PET_DATA_UPDATED_EVENT } from "@/lib/app-events";
import { import {
@@ -45,5 +47,20 @@ export function AvatarPageContent() {
); );
} }
return <PetHabitat customization={customization} fillViewport />; return (
<div className="flex w-full flex-col">
<div className="bit-home-pet-stage">
<PetHabitat customization={customization} fillViewport />
</div>
<section className="grid w-full gap-6 pt-6 lg:grid-cols-2 lg:items-start">
<div id="bit-daily-tasks">
<HabitTracker mode="daily" />
</div>
<div id="bit-daily-quiz">
<DailyQuizForm />
</div>
</section>
</div>
);
} }

View File

@@ -108,7 +108,7 @@ export function AvatarStatusCard({ customization }: AvatarStatusCardProps) {
</p> </p>
{!hasCheckedInToday ? ( {!hasCheckedInToday ? (
<Button asChild className="w-full"> <Button asChild className="w-full">
<Link href={routes.dailyQuiz}>Take today&apos;s quiz</Link> <Link href={`${routes.avatar}#bit-daily-quiz`}>Take today&apos;s quiz</Link>
</Button> </Button>
) : null} ) : null}
</CardContent> </CardContent>

View File

@@ -1,7 +1,6 @@
"use client"; "use client";
import { CheckCircle2 } from "lucide-react"; import { CheckCircle2 } from "lucide-react";
import Link from "next/link";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { WellnessSlider } from "@/components/daily-quiz/wellness-slider"; import { WellnessSlider } from "@/components/daily-quiz/wellness-slider";
@@ -32,7 +31,6 @@ import {
import { HABIT_PET_DATA_UPDATED_EVENT } from "@/lib/app-events"; import { HABIT_PET_DATA_UPDATED_EVENT } from "@/lib/app-events";
import { saveDailyEntry } from "@/lib/daily-quiz-storage"; import { saveDailyEntry } from "@/lib/daily-quiz-storage";
import { JOURNAL_MAX_LENGTH } from "@/lib/journal-safety"; import { JOURNAL_MAX_LENGTH } from "@/lib/journal-safety";
import { routes } from "@/lib/routes";
export function DailyQuizForm() { export function DailyQuizForm() {
const cachedQuiz = getCachedQuizTabData(); const cachedQuiz = getCachedQuizTabData();
@@ -161,14 +159,7 @@ export function DailyQuizForm() {
</p> </p>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Your answers are saved below. Come back tomorrow for your next Your answers are saved below. Come back tomorrow for your next
check-in. How you did today affects your bit. Spend time with{" "} check-in. How you did today affects your bit.
<Link
href={routes.avatar}
className="font-medium text-primary underline-offset-2 hover:underline"
>
your bit
</Link>{" "}
whenever you want to see how they are doing.
</p> </p>
<DailyQuizCountdown <DailyQuizCountdown
onAvailable={() => { onAvailable={() => {

View File

@@ -30,7 +30,7 @@ export function DailyQuizLinkButton() {
return ( return (
<Button asChild className="w-full" variant="outline"> <Button asChild className="w-full" variant="outline">
<Link href={routes.dailyQuiz}>Open daily quiz</Link> <Link href={`${routes.avatar}#bit-daily-quiz`}>Open daily quiz</Link>
</Button> </Button>
); );
} }

View File

@@ -3,14 +3,7 @@
import Link from "next/link"; import Link from "next/link";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { forwardRef } from "react"; import { forwardRef } from "react";
import { import { Home, Palette, ShoppingBag, UserRound } from "lucide-react";
Home,
ListPlus,
Palette,
ShoppingBag,
Sparkles,
UserRound,
} from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { appNavItems, routes, type NavItem } from "@/lib/routes"; import { appNavItems, routes, type NavItem } from "@/lib/routes";
@@ -31,17 +24,13 @@ const gridColsClass = {
const navIcons = { const navIcons = {
[routes.avatar]: Home, [routes.avatar]: Home,
[routes.customize]: Palette, [routes.customize]: Palette,
[routes.habits]: ListPlus,
[routes.dailyQuiz]: Sparkles,
[routes.shop]: ShoppingBag, [routes.shop]: ShoppingBag,
[routes.profile]: UserRound, [routes.profile]: UserRound,
} as const; } as const;
const prefetchByRoute: Partial<Record<string, () => void>> = { const prefetchByRoute: Partial<Record<string, () => void>> = {
[routes.habits]: () => { [routes.avatar]: () => {
void prefetchHabitsTabData(); void prefetchHabitsTabData();
},
[routes.dailyQuiz]: () => {
void prefetchQuizTabData(); void prefetchQuizTabData();
}, },
}; };

View File

@@ -18,8 +18,6 @@ export type AppRoute = (typeof routes)[keyof typeof routes];
export const appNavItems = [ export const appNavItems = [
{ href: routes.avatar, label: "Bit", shortLabel: "Bit" }, { href: routes.avatar, label: "Bit", shortLabel: "Bit" },
{ href: routes.customize, label: "Customize", shortLabel: "Style" }, { href: routes.customize, label: "Customize", shortLabel: "Style" },
{ href: routes.habits, label: "Habits", shortLabel: "Habits" },
{ href: routes.dailyQuiz, label: "Daily Quiz", shortLabel: "Quiz" },
{ href: routes.shop, label: "Shop", shortLabel: "Shop" }, { href: routes.shop, label: "Shop", shortLabel: "Shop" },
{ href: routes.profile, label: "Profile", shortLabel: "Profile" }, { href: routes.profile, label: "Profile", shortLabel: "Profile" },
] as const; ] as const;