feat: maintenance banner, activities log, pinned note, event templates, weekly summary cron
Maintenance mode banner: - App layout reads SystemConfig maintenance_mode at server render time - Amber sticky banner for regular users, dimmed indicator for superadmin Baby activities (3 new event types): - BATH (Bath icon, sky, timer+duration) - WALK / Balade (Footprints icon, lime) - TUMMY_TIME (Baby icon, amber) - Added to EventType enum, EVENT_CONFIG, event-icon.tsx, dashboard quick-log Pinned family note: - Shared across all family members, shown at top of dashboard - Inline edit with author + timestamp; /api/family/pinned-note GET/PATCH - pinnedNote + pinnedNoteUpdatedAt + pinnedNoteAuthor fields on Family model Event templates: - Named quick-log presets per family (type + label + metadata) - Dashboard row: tap to open pre-filled EventModal; hover ✕ to delete - Dropdown to create new template; /api/event-templates GET/POST + /[id] PATCH/DELETE - EventTemplate model in schema Weekly summary cron: - POST /api/cron/weekly-summary — auth via Bearer cron_secret (SystemConfig or env) - Per family, per baby: feeds count, sleep total+avg, diaper count, latest weight - Sends Pushover to all family members with pushoverUserKey - Optional body.familyId to target one family Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,16 +3,42 @@ import { redirect } from "next/navigation";
|
||||
import { SidebarNav, BottomNav } from "@/components/nav";
|
||||
import { BabyProvider } from "@/contexts/baby-context";
|
||||
import { QuickAddFab } from "@/components/quick-add-fab";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
|
||||
async function getMaintenanceMode(): Promise<boolean> {
|
||||
try {
|
||||
const row = await prisma.systemConfig.findUnique({ where: { key: "maintenance_mode" } });
|
||||
return row?.value === "true";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function AppLayout({ children }: { children: React.ReactNode }) {
|
||||
const session = await auth();
|
||||
if (!session?.user) redirect("/auth/login");
|
||||
|
||||
const maintenance = await getMaintenanceMode();
|
||||
const isSuperAdmin = (session.user as { isSuperAdmin?: boolean })?.isSuperAdmin;
|
||||
|
||||
return (
|
||||
<BabyProvider>
|
||||
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
|
||||
{maintenance && (
|
||||
<div className={`fixed top-0 left-0 right-0 z-[100] px-4 py-2.5 flex items-center gap-2 justify-center text-sm font-medium shadow-md ${
|
||||
isSuperAdmin
|
||||
? "bg-amber-400/90 text-amber-900 text-xs py-1.5"
|
||||
: "bg-amber-500 text-white"
|
||||
}`}>
|
||||
<AlertTriangle className="w-4 h-4 flex-shrink-0" />
|
||||
{isSuperAdmin
|
||||
? "Mode maintenance actif (visible des utilisateurs)"
|
||||
: "Maintenance en cours — certaines fonctionnalités peuvent être indisponibles"}
|
||||
</div>
|
||||
)}
|
||||
<SidebarNav />
|
||||
<main className="app-main min-h-screen">
|
||||
<main className={`app-main min-h-screen${maintenance ? " pt-10" : ""}`}>
|
||||
{children}
|
||||
</main>
|
||||
<BottomNav />
|
||||
|
||||
Reference in New Issue
Block a user