feat: build production-ready wtr weather PWA
This commit is contained in:
13
components/states/empty-state.tsx
Normal file
13
components/states/empty-state.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import { CircleCheckBig } from "lucide-react";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
||||
export function EmptyState({ title, description, icon: Icon = CircleCheckBig }: { title: string; description: string; icon?: LucideIcon }) {
|
||||
return (
|
||||
<Card className="flex min-h-52 flex-col items-center justify-center p-8 text-center">
|
||||
<div className="mb-4 rounded-full bg-emerald-500/10 p-3 text-emerald-600 dark:text-emerald-300"><Icon className="size-6" /></div>
|
||||
<h2 className="text-lg font-semibold">{title}</h2>
|
||||
<p className="mt-2 max-w-md text-sm leading-6 text-slate-600 dark:text-slate-300">{description}</p>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
14
components/states/error-state.tsx
Normal file
14
components/states/error-state.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { RefreshCw, TriangleAlert } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
||||
export function ErrorState({ title = "Nie udało się pobrać danych", description = "Sprawdź połączenie i spróbuj ponownie.", onRetry }: { title?: string; description?: string; onRetry: () => void }) {
|
||||
return (
|
||||
<Card className="flex min-h-52 flex-col items-center justify-center p-8 text-center">
|
||||
<div className="mb-4 rounded-full bg-amber-500/15 p-3 text-amber-700 dark:text-amber-300"><TriangleAlert className="size-6" /></div>
|
||||
<h2 className="text-lg font-semibold">{title}</h2>
|
||||
<p className="mb-5 mt-2 max-w-md text-sm leading-6 text-slate-600 dark:text-slate-300">{description}</p>
|
||||
<Button variant="glass" onClick={onRetry}><RefreshCw className="size-4" />Spróbuj ponownie</Button>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
16
components/states/loading-skeleton.tsx
Normal file
16
components/states/loading-skeleton.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function LoadingSkeleton({ className = "" }: { className?: string }) {
|
||||
return <div className={cn("animate-pulse rounded-[1.75rem] bg-white/40 dark:bg-white/10", className)} aria-label="Ładowanie danych" />;
|
||||
}
|
||||
|
||||
export function PageLoadingSkeleton() {
|
||||
return (
|
||||
<div className="space-y-5" aria-busy="true">
|
||||
<LoadingSkeleton className="h-[25rem]" />
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{Array.from({ length: 4 }, (_, index) => <LoadingSkeleton className="h-36" key={index} />)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user