Adds a new "bangs" module with a dashboard widget that tracks household bang events. The widget shows the total count, a configurable recent-bang list, and an "Add Bang" button that accepts a backdatable date. On submission, a full celebration sequence fires: screen flash, widget shake, count pop animation, synthesized firework sound (Web Audio API), 50 full-screen emoji particles via portal, canvas-confetti star bursts, side cannons, and a timed sequence of 7 firework bursts. - New bang_events table (migration 0017) - canvas-confetti dependency for fireworks/confetti effects - CSS keyframe animations: shake, countPop, emojiFloat - Fixes pre-existing Drizzle snapshot chain collision (0007/0008) - Adds OpenPlantBook env vars to compose.yaml
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import { z } from "zod";
|
|
import type { ModuleManifest, WidgetContext } from "../_core/module";
|
|
import { getBangStats } from "./server/queries";
|
|
import { BangWidget } from "./components/bang-widget";
|
|
|
|
const bangWidgetConfigSchema = z.object({
|
|
maxRecentBangs: z.number().int().min(1).max(20).default(5),
|
|
});
|
|
|
|
async function BangWidgetServer({ config, ctx }: { config: unknown; ctx: WidgetContext }) {
|
|
const parsed = bangWidgetConfigSchema.parse(config);
|
|
const stats = await getBangStats(ctx.householdId, parsed.maxRecentBangs);
|
|
return <BangWidget stats={stats} maxRecentBangs={parsed.maxRecentBangs} />;
|
|
}
|
|
|
|
const bangsManifest: ModuleManifest = {
|
|
id: "bangs",
|
|
name: "Bangs",
|
|
entities: [
|
|
{
|
|
type: "bangs.event",
|
|
label: { singular: "Bang", plural: "Bangs" },
|
|
resolveUrl: () => "/",
|
|
renderActivity: (entry) => {
|
|
const date = entry.payload?.occurredOn as string | undefined;
|
|
return date ? `Recorded a bang on ${date}` : "Recorded a bang";
|
|
},
|
|
},
|
|
],
|
|
dashboardWidgets: [
|
|
{
|
|
id: "bangs.counter",
|
|
title: "Bang Counter",
|
|
description: "Track and celebrate bangs with your household.",
|
|
category: "Fun",
|
|
defaultSize: { w: 3, h: 3 },
|
|
minSize: { w: 2, h: 2 },
|
|
defaultPriority: 60,
|
|
configSchema: bangWidgetConfigSchema,
|
|
defaultConfig: { maxRecentBangs: 5 },
|
|
render: (props) => <BangWidgetServer {...props} />,
|
|
},
|
|
],
|
|
};
|
|
|
|
export default bangsManifest;
|