81 lines
2.9 KiB
TypeScript
81 lines
2.9 KiB
TypeScript
import Link from "next/link";
|
||
import type { PlatformApp } from "@/lib/apps-catalog";
|
||
import { Badge } from "./Badge";
|
||
|
||
export interface AppTileProps {
|
||
app: PlatformApp;
|
||
onClick?: () => void;
|
||
variant?: "default" | "compact";
|
||
}
|
||
|
||
function AppTileContent({ app, variant = "default" }: { app: PlatformApp; variant?: "default" | "compact" }) {
|
||
const isAvailable = app.status === "available";
|
||
const isCompact = variant === "compact";
|
||
|
||
return (
|
||
<>
|
||
<div
|
||
className={`relative flex items-center justify-center rounded-[22px] bg-gradient-to-br ${app.gradient} shadow-lg shadow-black/10 transition-transform duration-300 group-hover:scale-105 group-hover:shadow-xl ${
|
||
isCompact ? "h-14 w-14 text-2xl" : "h-[72px] w-[72px] text-3xl sm:h-20 sm:w-20 sm:text-4xl"
|
||
}`}
|
||
>
|
||
<span role="img" aria-hidden>
|
||
{app.icon}
|
||
</span>
|
||
{!isAvailable ? (
|
||
<span className="absolute -bottom-1 -left-1">
|
||
<Badge variant="muted">بهزودی</Badge>
|
||
</span>
|
||
) : null}
|
||
{isAvailable ? (
|
||
<span className="absolute -bottom-1 -left-1 opacity-0 transition-opacity group-hover:opacity-100">
|
||
<Badge variant="primary">فعال</Badge>
|
||
</span>
|
||
) : null}
|
||
</div>
|
||
<div className="min-w-0 flex-1">
|
||
<p className={`truncate font-bold text-secondary ${isCompact ? "text-sm" : "text-sm sm:text-[15px]"}`}>
|
||
{app.name}
|
||
</p>
|
||
{!isCompact ? (
|
||
<p className="mt-0.5 line-clamp-2 text-xs text-gray-500">{app.description}</p>
|
||
) : null}
|
||
</div>
|
||
{isAvailable && app.href ? (
|
||
<span className="mt-auto text-xs font-medium text-primary opacity-0 transition-opacity group-hover:opacity-100">
|
||
ورود ←
|
||
</span>
|
||
) : null}
|
||
</>
|
||
);
|
||
}
|
||
|
||
const tileClassName =
|
||
"group flex w-full flex-col items-center gap-3 rounded-2xl border border-transparent bg-white p-3 text-center shadow-sm transition-all duration-300 hover:border-[var(--color-primary-muted)] hover:bg-[var(--color-primary-soft)] hover:shadow-md sm:p-4";
|
||
|
||
const disabledClassName =
|
||
"group flex w-full flex-col items-center gap-3 rounded-2xl border border-gray-100 bg-gray-50/60 p-3 text-center opacity-70 sm:p-4";
|
||
|
||
export function AppTile({ app, onClick, variant = "default" }: AppTileProps) {
|
||
const isAvailable = app.status === "available";
|
||
|
||
if (isAvailable && app.href && !onClick) {
|
||
return (
|
||
<Link href={app.href} className={tileClassName}>
|
||
<AppTileContent app={app} variant={variant} />
|
||
</Link>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<button
|
||
type="button"
|
||
onClick={onClick}
|
||
disabled={!isAvailable && !onClick}
|
||
className={isAvailable || onClick ? tileClassName : disabledClassName}
|
||
>
|
||
<AppTileContent app={app} variant={variant} />
|
||
</button>
|
||
);
|
||
}
|