"use client";
import {
ChangeEvent,
ReactNode,
SelectHTMLAttributes,
TextareaHTMLAttributes,
InputHTMLAttributes,
} from "react";
import { Button } from "@/components/ui";
export const inputClass =
"mt-1 w-full rounded-xl border border-gray-200 px-4 py-2.5 text-sm focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary disabled:bg-gray-50";
export const labelClass = "block text-sm font-medium text-secondary";
export const cardClass =
"rounded-2xl border border-gray-100 bg-white p-6 shadow-sm";
export function Field({
label,
hint,
children,
required,
}: {
label: string;
hint?: string;
required?: boolean;
children: ReactNode;
}) {
return (
);
}
interface TextFieldProps extends InputHTMLAttributes {
label: string;
hint?: string;
onValue?: (v: string) => void;
}
export function TextField({ label, hint, required, onValue, onChange, className, ...props }: TextFieldProps) {
return (
) => {
onValue?.(e.target.value);
onChange?.(e);
}}
{...props}
/>
);
}
interface TextareaFieldProps extends TextareaHTMLAttributes {
label: string;
hint?: string;
onValue?: (v: string) => void;
}
export function TextareaField({ label, hint, required, onValue, onChange, ...props }: TextareaFieldProps) {
return (
);
}
interface SelectFieldProps extends SelectHTMLAttributes {
label: string;
hint?: string;
options: { value: string; label: string }[];
onValue?: (v: string) => void;
}
export function SelectField({ label, hint, required, options, onValue, onChange, ...props }: SelectFieldProps) {
return (
);
}
export function Banner({
variant,
children,
}: {
variant: "error" | "success" | "info";
children: ReactNode;
}) {
if (!children) return null;
const styles = {
error: "bg-red-50 text-red-600",
success: "bg-green-50 text-green-700",
info: "bg-blue-50 text-blue-700",
}[variant];
return (
{children}
);
}
export function Modal({
open,
title,
onClose,
children,
footer,
}: {
open: boolean;
title: string;
onClose: () => void;
children: ReactNode;
footer?: ReactNode;
}) {
if (!open) return null;
return (
e.stopPropagation()}
>
{title}
{children}
{footer &&
{footer}
}
);
}
const STATUS_STYLES: Record = {
active: "bg-green-100 text-green-700",
trialing: "bg-blue-100 text-blue-700",
pending_activation: "bg-amber-100 text-amber-700",
draft: "bg-gray-100 text-gray-600",
suspended: "bg-red-100 text-red-700",
inactive: "bg-gray-100 text-gray-600",
maintenance: "bg-amber-100 text-amber-700",
archived: "bg-gray-100 text-gray-500",
deleted: "bg-red-100 text-red-700",
canceled: "bg-red-100 text-red-700",
expired: "bg-gray-100 text-gray-500",
past_due: "bg-amber-100 text-amber-700",
};
const STATUS_LABELS: Record = {
active: "فعال",
trialing: "آزمایشی",
pending_activation: "در انتظار فعالسازی",
draft: "پیشنویس",
suspended: "معلق",
inactive: "غیرفعال",
maintenance: "در حال تعمیر",
archived: "بایگانیشده",
deleted: "حذفشده",
canceled: "لغوشده",
expired: "منقضی",
past_due: "معوق",
};
export function StatusBadge({ status }: { status: string }) {
const style = STATUS_STYLES[status] || "bg-gray-100 text-gray-600";
return (
{STATUS_LABELS[status] || status}
);
}
export function EmptyState({ message }: { message: string }) {
return {message}
;
}
export function AdminPageHeader({
title,
subtitle,
action,
}: {
title: string;
subtitle?: string;
action?: ReactNode;
}) {
return (
{title}
{subtitle &&
{subtitle}
}
{action &&
{action}
}
);
}
export { Button };