Merge remote-tracking branch 'origin/goutamnextflow' into feat/projects

# Conflicts:
#	src/app/dashboard/dashboard.css
#	src/components/dashboard/dashboard.tsx
#	src/components/dashboard/ui.tsx
This commit is contained in:
abe-kap
2026-07-23 12:52:13 -04:00
125 changed files with 24845 additions and 99 deletions
+13 -5
View File
@@ -24,7 +24,8 @@ import {
LayoutDashboard, Building2, FolderKanban, UserPlus, BadgeCheck, Filter,
Truck, CloudLightning, Map as MapIcon, PenTool, Calculator, CalendarDays,
Trophy, ListChecks, Users, Settings, Sparkles, MoreHorizontal,
UsersRound, Download, type LucideIcon,
UsersRound, Image as ImageIcon, Images, File, FolderOpen, Download,
Video, Play, LayoutGrid, ZoomIn, type LucideIcon,
} from "lucide-react";
/* ---------------------------------------------------------- */
@@ -49,7 +50,11 @@ const ICONS: Record<string, LucideIcon> = {
storm: CloudLightning, territory: MapIcon, procanvas: PenTool,
estimates: Calculator, schedule: CalendarDays, leaderboard: Trophy,
subtasks: ListChecks, people: Users, settings: Settings, ai: Sparkles,
team: UsersRound, dots: MoreHorizontal, download: Download,
team: UsersRound, dots: MoreHorizontal,
// media / gallery (also used by messenger.tsx, which already asks for image/file)
image: ImageIcon, gallery: Images, file: File, folder: FolderOpen,
download: Download, video: Video, play: Play, grid: LayoutGrid,
filter: Filter, zoom: ZoomIn, sparkle: Sparkles, "map-pin": MapPin,
};
export function Icon({ name, size = 18, className, strokeWidth = 2 }: { name: string; size?: number; className?: string; strokeWidth?: number }) {
@@ -263,7 +268,7 @@ export function Modal({ open, onClose, title, subtitle, icon, children, footer,
/* Toast */
/* ---------------------------------------------------------- */
type Toast = { id: number; tone: "success" | "info" | "error"; title: string; desc?: string };
type Toast = { id: number; tone: "success" | "info" | "error"; title: string; desc?: string; onClick?: () => void };
type ToastCtx = { push: (t: Omit<Toast, "id">) => void };
const ToastContext = createContext<ToastCtx | null>(null);
@@ -286,9 +291,12 @@ export function ToastProvider({ children }: { children: ReactNode }) {
{children}
<div className="ds-toasts">
{items.map((t) => (
<div key={t.id} className={`ds-toast tone-${t.tone}`}>
<div key={t.id} className={`ds-toast tone-${t.tone}${t.onClick ? " is-clickable" : ""}`}>
<Icon name={t.tone === "success" ? "check-circle" : t.tone === "error" ? "alert" : "info"} size={18} />
<div className="ds-toast-body">
<div
className="ds-toast-body"
{...(t.onClick ? { role: "button", tabIndex: 0, onClick: () => { t.onClick?.(); setItems((s) => s.filter((x) => x.id !== t.id)); } } : {})}
>
<div className="ds-toast-title">{t.title}</div>
{t.desc && <div className="ds-toast-desc">{t.desc}</div>}
</div>