Add Oudelaa dashboard API integration
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled
هذا الالتزام موجود في:
80
oudelaa_dashboard/components/ui/toast.tsx
Normal file
80
oudelaa_dashboard/components/ui/toast.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { X } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type ToastVariant = "default" | "success" | "warning" | "danger";
|
||||
|
||||
type ToastItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
variant?: ToastVariant;
|
||||
};
|
||||
|
||||
type ToastContextValue = {
|
||||
toast: (item: Omit<ToastItem, "id">) => void;
|
||||
};
|
||||
|
||||
const ToastContext = React.createContext<ToastContextValue | null>(null);
|
||||
|
||||
function getToastId() {
|
||||
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
return `toast_${Date.now()}_${Math.random().toString(16).slice(2)}`;
|
||||
}
|
||||
|
||||
const variantStyles: Record<ToastVariant, string> = {
|
||||
default: "border-border bg-card text-foreground",
|
||||
success: "border-emerald-500/40 bg-emerald-500/10 text-emerald-100",
|
||||
warning: "border-amber-500/40 bg-amber-500/10 text-amber-100",
|
||||
danger: "border-rose-500/40 bg-rose-500/10 text-rose-100",
|
||||
};
|
||||
|
||||
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||||
const [toasts, setToasts] = React.useState<ToastItem[]>([]);
|
||||
|
||||
const toast = React.useCallback((item: Omit<ToastItem, "id">) => {
|
||||
const id = getToastId();
|
||||
setToasts((prev) => [...prev, { id, ...item }]);
|
||||
window.setTimeout(() => {
|
||||
setToasts((prev) => prev.filter((toastItem) => toastItem.id !== id));
|
||||
}, 3200);
|
||||
}, []);
|
||||
|
||||
const remove = React.useCallback((id: string) => {
|
||||
setToasts((prev) => prev.filter((toastItem) => toastItem.id !== id));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ToastContext.Provider value={{ toast }}>
|
||||
{children}
|
||||
<div className="fixed bottom-6 left-6 z-50 flex w-[90vw] max-w-sm flex-col gap-3">
|
||||
{toasts.map((item) => (
|
||||
<div key={item.id} className={cn("frame-panel border px-4 py-3 shadow-glow", variantStyles[item.variant ?? "default"])}>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<p className="text-sm font-semibold">{item.title}</p>
|
||||
{item.description ? <p className="mt-1 text-xs text-muted-foreground">{item.description}</p> : null}
|
||||
</div>
|
||||
<button className="rounded-md p-1 text-muted-foreground hover:text-foreground" onClick={() => remove(item.id)}>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ToastContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useToast() {
|
||||
const context = React.useContext(ToastContext);
|
||||
if (!context) {
|
||||
throw new Error("useToast must be used within ToastProvider");
|
||||
}
|
||||
return context;
|
||||
}
|
||||
المرجع في مشكلة جديدة
حظر مستخدم