fix(deploy): pin distinct image tags per compose (booklib/{api,web}:{dev,prod}); same project name shared default tags so dev up without --build ran the prod image
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { useEffect, useState, type ReactNode } from "react";
|
||||
|
||||
type Toast = { id: number; kind: "ok" | "err"; text: ReactNode };
|
||||
|
||||
const items: Toast[] = [];
|
||||
const subs = new Set<(t: Toast[]) => void>();
|
||||
let nextId = 1;
|
||||
|
||||
export function toast(kind: Toast["kind"], text: ReactNode): void {
|
||||
const t: Toast = { id: nextId++, kind, text };
|
||||
items.push(t);
|
||||
subs.forEach((f) => f([...items]));
|
||||
setTimeout(() => {
|
||||
const i = items.findIndex((x) => x.id === t.id);
|
||||
if (i >= 0) items.splice(i, 1);
|
||||
subs.forEach((f) => f([...items]));
|
||||
}, 4000);
|
||||
}
|
||||
|
||||
export function Toaster() {
|
||||
const [list, setList] = useState<Toast[]>([]);
|
||||
useEffect(() => {
|
||||
subs.add(setList);
|
||||
return () => {
|
||||
subs.delete(setList);
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<div className="fixed bottom-4 right-4 z-50 flex flex-col gap-2">
|
||||
{list.map((t) => (
|
||||
<div
|
||||
key={t.id}
|
||||
role="status"
|
||||
className={`max-w-sm rounded-lg px-4 py-2 text-sm shadow-lg ${
|
||||
t.kind === "ok" ? "bg-emerald-900 text-emerald-100" : "bg-red-900 text-red-100"
|
||||
}`}
|
||||
>
|
||||
{t.text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user