feat: switch between provinces
This commit is contained in:
@@ -6,14 +6,24 @@ import { motion, AnimatePresence } from "framer-motion";
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
GlobeAsiaAustraliaIcon,
|
||||
MapPinIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { getInspectionMenuItems } from "../config/menuItems";
|
||||
|
||||
const ADMIN_PROVINCES = [
|
||||
{ value: "hamedan", label: "همدان" },
|
||||
{ value: "markazi", label: "مرکزی" },
|
||||
] as const;
|
||||
|
||||
export const Menu = () => {
|
||||
const { profile } = useUserProfileStore();
|
||||
const { profile, updateProfile } = useUserProfileStore();
|
||||
const navigate = useNavigate();
|
||||
const menuItems = getInspectionMenuItems(profile?.permissions || []);
|
||||
const [openIndex, setOpenIndex] = useState<number | null>(null);
|
||||
const hasAdmin =
|
||||
Array.isArray(profile?.permissions) &&
|
||||
profile.permissions.includes("admin");
|
||||
const currentProvince = profile?.province || "hamedan";
|
||||
|
||||
const toggleSubmenu = (index: number) => {
|
||||
setOpenIndex((prev) => (prev === index ? null : index));
|
||||
@@ -27,7 +37,7 @@ export const Menu = () => {
|
||||
منو
|
||||
</h1>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="mb-4 space-y-3">
|
||||
<button
|
||||
onClick={() => navigate({ to: "/" })}
|
||||
className="w-full flex items-center justify-center gap-2 px-4 py-3 rounded-xl bg-primary-500 hover:bg-primary-600 cursor-pointer dark:bg-primary-800 dark:hover:bg-primary-700 text-white font-semibold text-sm transition-all duration-200 shadow-md hover:shadow-lg"
|
||||
@@ -35,6 +45,30 @@ export const Menu = () => {
|
||||
<GlobeAsiaAustraliaIcon className="w-5 h-5" />
|
||||
<span>مشاهده نقشه</span>
|
||||
</button>
|
||||
{hasAdmin && (
|
||||
<div className="flex flex-col gap-2 p-3 rounded-xl bg-white dark:bg-dark-700 border border-gray-200 dark:border-dark-600">
|
||||
<div className="flex items-center gap-2 text-sm font-medium text-gray-600 dark:text-gray-400">
|
||||
<MapPinIcon className="w-4 h-4 shrink-0" />
|
||||
<span>استان</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{ADMIN_PROVINCES.map(({ value, label }) => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
onClick={() => updateProfile({ province: value })}
|
||||
className={`px-4 py-2.5 rounded-lg text-sm font-medium transition-all ${
|
||||
currentProvince === value
|
||||
? "bg-primary-500 text-white dark:bg-primary-600 shadow-md"
|
||||
: "bg-gray-100 dark:bg-dark-600 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-dark-500"
|
||||
}`}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
|
||||
@@ -5,12 +5,13 @@ import { useDashboardTabStore } from "./dashboardTabStore";
|
||||
interface UseUserProfileStore {
|
||||
profile?: Record<string, any> | null;
|
||||
setUserProfile: (profile: Record<string, any>) => void;
|
||||
updateProfile: (updates: Partial<Record<string, any>>) => void;
|
||||
clearProfile: () => void;
|
||||
}
|
||||
|
||||
const arePermissionsEqual = (
|
||||
permissions1?: string[],
|
||||
permissions2?: string[]
|
||||
permissions2?: string[],
|
||||
): boolean => {
|
||||
if (!permissions1 && !permissions2) return true;
|
||||
if (!permissions1 || !permissions2) return false;
|
||||
@@ -24,7 +25,7 @@ const arePermissionsEqual = (
|
||||
|
||||
const areProfilesEqual = (
|
||||
currentProfile: Record<string, any> | null | undefined,
|
||||
newProfile: Record<string, any>
|
||||
newProfile: Record<string, any>,
|
||||
): boolean => {
|
||||
if (!currentProfile) return false;
|
||||
|
||||
@@ -35,10 +36,10 @@ const areProfilesEqual = (
|
||||
}
|
||||
|
||||
const currentKeys = Object.keys(currentProfile).filter(
|
||||
(key) => key !== "permissions"
|
||||
(key) => key !== "permissions",
|
||||
);
|
||||
const newKeys = Object.keys(newProfile).filter(
|
||||
(key) => key !== "permissions"
|
||||
(key) => key !== "permissions",
|
||||
);
|
||||
|
||||
if (currentKeys.length !== newKeys.length) return false;
|
||||
@@ -72,10 +73,15 @@ export const useUserProfileStore = create<UseUserProfileStore>()(
|
||||
console.log("profile", profile);
|
||||
}
|
||||
},
|
||||
updateProfile: (updates) => {
|
||||
const currentProfile = get().profile;
|
||||
if (!currentProfile) return;
|
||||
set({ profile: { ...currentProfile, ...updates } });
|
||||
},
|
||||
clearProfile: () => set({ profile: null }),
|
||||
}),
|
||||
{ name: "userprofile" }
|
||||
)
|
||||
{ name: "userprofile" },
|
||||
),
|
||||
);
|
||||
|
||||
interface UseUserStore {
|
||||
@@ -97,6 +103,6 @@ export const useUserStore = create<UseUserStore>()(
|
||||
}),
|
||||
{
|
||||
name: "user",
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -15,8 +15,14 @@ import {
|
||||
MagnifyingGlassIcon,
|
||||
BuildingOfficeIcon,
|
||||
GlobeAsiaAustraliaIcon,
|
||||
MapPinIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
|
||||
const ADMIN_PROVINCES = [
|
||||
{ value: "hamedan", label: "همدان" },
|
||||
{ value: "markazi", label: "مرکزی" },
|
||||
] as const;
|
||||
|
||||
const containerVariants = {
|
||||
hidden: {},
|
||||
visible: { transition: { staggerChildren: 0.03 } },
|
||||
@@ -66,8 +72,12 @@ const sidebarVariants = {
|
||||
|
||||
export const SideBar = () => {
|
||||
const isMobile = checkIsMobile();
|
||||
const { profile } = useUserProfileStore();
|
||||
const { profile, updateProfile } = useUserProfileStore();
|
||||
const menuItems = getInspectionMenuItems(profile?.permissions || []);
|
||||
const hasAdmin =
|
||||
Array.isArray(profile?.permissions) &&
|
||||
profile.permissions.includes("admin");
|
||||
const currentProvince = profile?.province || "hamedan";
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const { isSideBarOpen, toggleSideBar } = useSideBarStore();
|
||||
@@ -201,6 +211,30 @@ export const SideBar = () => {
|
||||
<span>مشاهده نقشه</span>
|
||||
</motion.button>
|
||||
)}
|
||||
{isSideBarOpen && hasAdmin && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center gap-2 text-xs font-medium text-gray-600 dark:text-gray-400">
|
||||
<MapPinIcon className="w-4 h-4 shrink-0" />
|
||||
<span>استان</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-1.5">
|
||||
{ADMIN_PROVINCES.map(({ value, label }) => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
onClick={() => updateProfile({ province: value })}
|
||||
className={`px-3 py-2 rounded-lg text-sm font-medium transition-all ${
|
||||
currentProvince === value
|
||||
? "bg-primary-500 text-white dark:bg-primary-600 shadow-md"
|
||||
: "bg-gray-100 dark:bg-dark-600 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-dark-500"
|
||||
}`}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user