import { useEffect, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Link } from "react-router-dom"; import { toast } from "sonner"; import SettingsLayout from "../components/layout/SettingsLayout"; import ConfirmDialog from "../components/ui/ConfirmDialog"; import Modal from "../components/ui/Modal"; import type { ApiResponse } from "../lib/api"; import { api } from "../lib/api"; import { formatDate, digitsOnly, IRAN_MOBILE_RE, IRAN_NATIONAL_CODE_RE } from "../lib/utils"; import { useSubscription } from "../hooks/useSubscription"; import { useAuthStore } from "../stores/authStore"; import type { Secretary, SecretaryPermissions } from "../types"; // ── SVG icons (copied verbatim from clinic-pro-tauri) ─────────────────────── const PlusIcon = () => ( ); const EyeIcon = () => ( ); const EditIcon = () => ( ); const ChevronDown = ({ open }: { open: boolean }) => ( ); // ── Avatar (first-letter gradient fallback, like tauri) ───────────────────── function Avatar({ name, size = 32 }: { name?: string; size?: number }) { const firstLetter = (name?.trim().charAt(0) || "?").toUpperCase(); return (
{firstLetter}
); } // ── Permission sections (based on existing clinicpro pages) ───────────────── const EMPTY_PERMISSIONS: SecretaryPermissions = { appointments: { view: false, create: false, cancel: false, update_status: false }, patients: { view: false, create: false, update: false, delete: false }, payments: { view: false, create: false, update: false, delete: false }, insurances: { view: false, create: false, update: false, delete: false }, addresses: { view: false, create: false, update: false, delete: false }, clinic_info: { view: false, update: false }, }; type PermSection = keyof SecretaryPermissions; const PERMISSION_SECTIONS: { key: PermSection; title: string; items: { key: string; label: string }[]; }[] = [ { key: "appointments", title: "مدیریت نوبت‌ها", items: [ { key: "view", label: "مشاهده نوبت‌ها" }, { key: "create", label: "ایجاد نوبت" }, { key: "cancel", label: "لغو نوبت" }, { key: "update_status", label: "تغییر وضعیت نوبت" }, ], }, { key: "patients", title: "پرونده بیماران", items: [ { key: "view", label: "مشاهده بیماران" }, { key: "create", label: "ایجاد بیمار" }, { key: "update", label: "ویرایش بیمار" }, { key: "delete", label: "حذف بیمار" }, ], }, { key: "payments", title: "مدیریت پرداخت‌ها", items: [ { key: "view", label: "مشاهده پرداخت‌ها" }, { key: "create", label: "ثبت پرداخت" }, { key: "update", label: "ویرایش پرداخت" }, { key: "delete", label: "حذف پرداخت" }, ], }, { key: "insurances", title: "مدیریت بیمه‌ها", items: [ { key: "view", label: "مشاهده بیمه‌ها" }, { key: "create", label: "ایجاد بیمه" }, { key: "update", label: "ویرایش بیمه" }, { key: "delete", label: "حذف بیمه" }, ], }, { key: "addresses", title: "آدرس‌ها", items: [ { key: "view", label: "مشاهده آدرس‌ها" }, { key: "create", label: "ایجاد آدرس" }, { key: "update", label: "ویرایش آدرس" }, { key: "delete", label: "حذف آدرس" }, ], }, { key: "clinic_info", title: "اطلاعات کلینیک", items: [ { key: "view", label: "مشاهده اطلاعات" }, { key: "update", label: "ویرایش اطلاعات" }, ], }, ]; function PermissionAccordions({ permissions, onChange, disabled, }: { permissions: SecretaryPermissions; onChange: (section: PermSection, item: string, value: boolean) => void; disabled?: boolean; }) { const [openKeys, setOpenKeys] = useState>( new Set(["appointments", "patients"]), ); const toggleOpen = (key: string) => { setOpenKeys((prev) => { const next = new Set(prev); next.has(key) ? next.delete(key) : next.add(key); return next; }); }; return (

مجوزهای دسترسی

{PERMISSION_SECTIONS.map((section) => { const open = openKeys.has(section.key); const sectionPerm = permissions[section.key] as Record; return (
{open && (
{section.items.map((item) => ( ))}
)}
); })}
); } // ── Text field (tauri DefaultTextField look) ──────────────────────────────── function DefaultTextField({ placeholder, value, onChange, disabled, multiline, rows, numeric, maxDigits, }: { placeholder?: string; value: string; onChange: (v: string) => void; disabled?: boolean; multiline?: boolean; rows?: number; /** فیلد فقط‌عددی: ارقام فارسی/عربی به لاتین تبدیل و غیررقم حذف می‌شود. */ numeric?: boolean; maxDigits?: number; }) { const cls = "w-full bg-[#FAFAFA] dark:bg-[#222433] rounded-[8px] border border-[#D7D7D7] dark:border-[#343645] " + "text-[#7E7E7E] dark:text-[#D7D8ED] text-[16px] font-normal px-[12px] py-[12.5px] outline-none " + "focus:border-[#5559CE] disabled:opacity-70"; if (multiline) { return (