"use client" //export const dynamic = 'force-dynamic' //export const revalidate = 0 import type React from "react" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" // app/admin/page.tsx // ... (other imports) // Updated import to get all necessary types and constants from types/user.ts import { type User, type UserRole, type Field, type Department, type Team, ROLE_NAMES, SHELTER_STATUS_NAMES, // You might need this if displaying status names DEPARTMENTS, // If you use this array anywhere for dropdowns/validation TEAMS, // If you use this array anywhere for dropdowns/validation FIELDS, // If you use this array anywhere for dropdowns/validation } from "@/types/user" // ... (rest of your component code) import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, } from "@/components/ui/alert-dialog" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Checkbox } from "@/components/ui/checkbox" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Alert, AlertDescription } from "@/components/ui/alert" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { ArrowRight, RotateCcw, Users, UserPlus, Clock, Trash2, Eye, KeyRound, RefreshCw, WifiOff, Zap, BarChart3, PieChart, UsersIcon, Globe, Building2, UserCog, MessageSquare, Lock, LockOpen, ArrowLeft, Home, } from "lucide-react" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { UserCategoryModal } from "@/components/user-category-modal" import { TeamUserCategoryModal } from "@/components/team-user-category-modal" import { StatsPieChart } from "@/components/stats-pie-chart" import { SimplePieChart } from "@/components/simple-pie-chart" import { useRealTimeUpdates } from "@/hooks/useRealTimeUpdates" import { useTeamRealTimeUpdates } from "@/hooks/useTeamRealTimeUpdates" import { DepartmentUserCategoryModal } from "@/components/department-user-category-modal" import { useDepartmentRealTimeUpdates } from "@/hooks/useDepartmentRealTimeUpdates" import { FieldUserCategoryModal } from "@/components/field-user-category-modal" import { useFieldRealTimeUpdates } from "@/hooks/useFieldRealTimeUpdates" import { ReportOnBehalfModal } from "@/components/report-on-behalf-modal" interface Stats { no_report: number in_shelter: number not_in_shelter: number no_alarm: number safe_after_exit: number } interface UserData { national_id: string name: string in_shelter?: string last_updated?: string is_admin: boolean must_change_password?: boolean field?: string department?: string team?: string lock_status?: boolean } export default function AdminPage() { const [user, setUser] = useState(null) const [activeTab, setActiveTab] = useState("team") // Global stats and data const [globalStats, setGlobalStats] = useState(null) const [globalUsers, setGlobalUsers] = useState([]) const [globalLastReset, setGlobalLastReset] = useState(null) const [globalResetCooldown, setGlobalResetCooldown] = useState(0) // Team stats and data const [teamStats, setTeamStats] = useState(null) const [teamUsers, setTeamUsers] = useState([]) const [teamName, setTeamName] = useState("") const [teamResetCooldown, setTeamResetCooldown] = useState(0) // Department stats and data const [departmentStats, setDepartmentStats] = useState(null) const [departmentUsers, setDepartmentUsers] = useState([]) const [departmentName, setDepartmentName] = useState("") const [departmentResetCooldown, setDepartmentResetCooldown] = useState(0) const [departmentChangedRows, setDepartmentChangedRows] = useState>(new Set()) const [departmentModalOpen, setDepartmentModalOpen] = useState(false) // Field stats and data const [fieldStats, setFieldStats] = useState(null) const [fieldUsers, setFieldUsers] = useState([]) const [fieldName, setFieldName] = useState("") const [fieldResetCooldown, setFieldResetCooldown] = useState(0) const [fieldChangedRows, setFieldChangedRows] = useState>(new Set()) const [fieldModalOpen, setFieldModalOpen] = useState(false) const [newUser, setNewUser] = useState({ name: "", isAdmin: false, field: "", department: "", team: "", role: "", }) const [message, setMessage] = useState("") const [loadingUsers, setLoadingUsers] = useState(false) const [modalOpen, setModalOpen] = useState(false) const [teamModalOpen, setTeamModalOpen] = useState(false) const [selectedCategory, setSelectedCategory] = useState("") const [selectedCategoryName, setSelectedCategoryName] = useState("") const [isRefreshing, setIsRefreshing] = useState(false) const [changedRows, setChangedRows] = useState>(new Set()) const [teamChangedRows, setTeamChangedRows] = useState>(new Set()) const [viewMode, setViewMode] = useState<"list" | "pie">("list") const [debugMode, setDebugMode] = useState(false) const [useSimpleChart, setUseSimpleChart] = useState(false) const router = useRouter() const [reportModalOpen, setReportModalOpen] = useState(false) const [selectedUserForReport, setSelectedUserForReport] = useState(null) // Global real-time updates const { isConnected: globalConnected, refetch: refetchGlobal } = useRealTimeUpdates((data) => { if (data.stats) { setGlobalStats(data.stats) } if (data.users) { const newChangedRows = new Set() data.users.forEach((newUser: UserData) => { const existingUser = globalUsers.find((u) => u.national_id === newUser.national_id) if ( existingUser && (existingUser.in_shelter !== newUser.in_shelter || existingUser.last_updated !== newUser.last_updated) ) { newChangedRows.add(newUser.national_id) } }) setGlobalUsers(data.users) setChangedRows(newChangedRows) if (newChangedRows.size > 0) { setTimeout(() => setChangedRows(new Set()), 3000) } } if (data.lastReset?.lastReset) { setGlobalLastReset(data.lastReset.lastReset) if (data.lastReset.timestamp) { const resetTime = new Date(data.lastReset.timestamp).getTime() const now = new Date().getTime() const cooldownMs = 2 * 60 // 2 minutes const remaining = Math.max(0, cooldownMs - (now - resetTime)) setGlobalResetCooldown(Math.ceil(remaining / 1000)) } } }) // Team real-time updates const { isConnected: teamConnected, refetch: refetchTeam } = useTeamRealTimeUpdates( user?.national_id || "", (data) => { if (data.stats) { setTeamStats(data.stats) } if (data.users) { const newChangedRows = new Set() data.users.forEach((newUser: UserData) => { const existingUser = teamUsers.find((u) => u.national_id === newUser.national_id) if ( existingUser && (existingUser.in_shelter !== newUser.in_shelter || existingUser.last_updated !== newUser.last_updated) ) { newChangedRows.add(newUser.national_id) } }) setTeamUsers(data.users) setTeamChangedRows(newChangedRows) if (newChangedRows.size > 0) { setTimeout(() => setTeamChangedRows(new Set()), 3000) } } if (data.team) { setTeamName(data.team) } }, ) // Department real-time updates const { isConnected: departmentConnected, refetch: refetchDepartment } = useDepartmentRealTimeUpdates( user?.national_id || "", (data) => { if (data.stats) { setDepartmentStats(data.stats) } if (data.users) { const newChangedRows = new Set() data.users.forEach((newUser: UserData) => { const existingUser = departmentUsers.find((u) => u.national_id === newUser.national_id) if ( existingUser && (existingUser.in_shelter !== newUser.in_shelter || existingUser.last_updated !== newUser.last_updated) ) { newChangedRows.add(newUser.national_id) } }) setDepartmentUsers(data.users) setDepartmentChangedRows(newChangedRows) if (newChangedRows.size > 0) { setTimeout(() => setDepartmentChangedRows(new Set()), 3000) } } if (data.department) { setDepartmentName(data.department) } }, ) // Field real-time updates const { isConnected: fieldConnected, refetch: refetchField } = useFieldRealTimeUpdates( user?.national_id || "", (data) => { if (data.stats) { setFieldStats(data.stats) } if (data.users) { const newChangedRows = new Set() data.users.forEach((newUser: UserData) => { const existingUser = fieldUsers.find((u) => u.national_id === newUser.national_id) if ( existingUser && (existingUser.in_shelter !== newUser.in_shelter || existingUser.last_updated !== newUser.last_updated) ) { newChangedRows.add(newUser.national_id) } }) setFieldUsers(data.users) setFieldChangedRows(newChangedRows) if (newChangedRows.size > 0) { setTimeout(() => setFieldChangedRows(new Set()), 3000) } } if (data.field) { setFieldName(data.field) } }, ) useEffect(() => { const userData = localStorage.getItem("user") if (!userData) { router.push("/login") return } const parsedUser = JSON.parse(userData) if (!["global_admin", "field_admin", "department_admin", "team_admin"].includes(parsedUser.role)) { router.push("/dashboard") return } setUser(parsedUser) }, [router]) useEffect(() => { if (globalResetCooldown > 0) { const timer = setTimeout(() => setGlobalResetCooldown(globalResetCooldown - 1), 1000) return () => clearTimeout(timer) } }, [globalResetCooldown]) useEffect(() => { if (teamResetCooldown > 0) { const timer = setTimeout(() => setTeamResetCooldown(teamResetCooldown - 1), 1000) return () => clearTimeout(timer) } }, [teamResetCooldown]) useEffect(() => { if (departmentResetCooldown > 0) { const timer = setTimeout(() => setDepartmentResetCooldown(departmentResetCooldown - 1), 1000) return () => clearTimeout(timer) } }, [departmentResetCooldown]) useEffect(() => { if (fieldResetCooldown > 0) { const timer = setTimeout(() => setFieldResetCooldown(fieldResetCooldown - 1), 1000) return () => clearTimeout(timer) } }, [fieldResetCooldown]) const handleGlobalResetAll = async () => { if (globalResetCooldown > 0) return try { const response = await fetch("/api/admin/reset-all", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ adminId: user?.national_id }), }) const data = await response.json() if (response.ok) { setMessage(data.message || "כל הסטטוסים אופסו בהצלחה") setGlobalResetCooldown(30) // 2 minutes setGlobalLastReset(`${user?.name} - ${new Date().toLocaleString("he-IL")}`) refetchGlobal() refetchTeam() // Also refresh team data refetchDepartment() refetchField() } else { // Handle cooldown error specifically if (response.status === 429 && data.remainingSeconds) { setGlobalResetCooldown(data.remainingSeconds) setMessage(`יש להמתין ${data.remainingSeconds} שניות לפני איפוס נוסף`) } else { setMessage(data.error || "שגיאה באיפוס הסטטוסים") } } } catch (err) { setMessage("שגיאה באיפוס הסטטוסים") } } const handleTeamReset = async () => { if (teamResetCooldown > 0) return try { const response = await fetch("/api/admin/team-reset", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ adminId: user?.national_id }), }) const data = await response.json() if (response.ok) { setMessage(data.message || `כל הסטטוסים של צוות ${data.team} אופסו בהצלחה`) setTeamResetCooldown(60) // 1 minute refetchTeam() refetchGlobal() // Also refresh global data refetchDepartment() refetchField() } else { if (response.status === 429 && data.remainingSeconds) { setTeamResetCooldown(data.remainingSeconds) setMessage(`יש להמתין ${data.remainingSeconds} שניות לפני איפוס צוות נוסף`) } else { setMessage(data.error || "שגיאה באיפוס הצוות") } } } catch (err) { setMessage("שגיאה באיפוס הצוות") } } const handleDepartmentReset = async () => { if (departmentResetCooldown > 0) return try { const response = await fetch("/api/admin/department-reset", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ adminId: user?.national_id }), }) const data = await response.json() if (response.ok) { setMessage(data.message || `כל הסטטוסים של מסגרת ${data.department} אופסו בהצלחה`) setDepartmentResetCooldown(90) // 1.5 minutes refetchDepartment() refetchGlobal() // Also refresh global data refetchTeam() refetchField() } else { if (response.status === 429 && data.remainingSeconds) { setDepartmentResetCooldown(data.remainingSeconds) setMessage(`יש להמתין ${data.remainingSeconds} שניות לפני איפוס מסגרת נוסף`) } else { setMessage(data.error || "שגיאה באיפוס המסגרת") } } } catch (err) { setMessage("שגיאה באיפוס המסגרת") } } const handleFieldReset = async () => { if (fieldResetCooldown > 0) return try { const response = await fetch("/api/admin/field-reset", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ adminId: user?.national_id }), }) const data = await response.json() if (response.ok) { setMessage(data.message || `כל הסטטוסים של תחום ${data.field} אופסו בהצלחה`) setFieldResetCooldown(120) // 2 minutes refetchField() refetchGlobal() // Also refresh global data refetchTeam() refetchDepartment() } else { if (response.status === 429 && data.remainingSeconds) { setFieldResetCooldown(data.remainingSeconds) setMessage(`יש להמתין ${data.remainingSeconds} שניות לפני איפוס תחום נוסף`) } else { setMessage(data.error || "שגיאה באיפוס התחום") } } } catch (err) { setMessage("שגיאה באיפוס התחום") } } const handleAddUser = async (e: React.FormEvent) => { e.preventDefault() if (!newUser.field || !newUser.department || !newUser.team || !newUser.role) { setMessage("יש לבחור תפקיד, תחום, מסגרת וצוות") return } try { const response = await fetch("/api/admin/add-user", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ...newUser, adminId: user?.national_id, }), }) const data = await response.json() if (response.ok) { setMessage(`${data.message}. הסיסמה הזמנית: password123`) setNewUser({ name: "", isAdmin: false, field: "", department: "", team: "", role: "" }) refetchGlobal() refetchTeam() refetchDepartment() refetchField() } else { setMessage(data.error || "שגיאה בהוספת משתמש") } } catch (err) { setMessage("שגיאה בחיבור לשרת") } } const handleDeleteUser = async (nationalId: string) => { try { const response = await fetch(`/api/admin/users/${nationalId}`, { method: "DELETE", }) if (response.ok) { setMessage("משתמש נמחק בהצלחה") refetchGlobal() refetchTeam() refetchDepartment() refetchField() } else { const data = await response.json() setMessage(data.error || "שגיאה במחיקת משתמש") } } catch (err) { setMessage("שגיאה בחיבור לשרת") } } const handleResetPassword = async (nationalId: string, userName: string) => { try { const response = await fetch("/api/admin/reset-password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ adminId: user?.national_id, targetUserId: nationalId, }), }) if (response.ok) { setMessage(`סיסמה אופסה בהצלחה עבור ${userName}. הסיסמה החדשה: password123`) refetchGlobal() refetchTeam() refetchDepartment() refetchField() } else { const data = await response.json() setMessage(data.error || "שגיאה באיפוס סיסמה") } } catch (err) { setMessage("שגיאה בחיבור לשרת") } } const handleToggleUserLock = async (nationalId: string, currentLockStatus: boolean, userName: string) => { try { const response = await fetch("/api/admin/toggle-user-lock", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ adminId: user?.national_id, targetUserId: nationalId, lockStatus: !currentLockStatus, }), }) const data = await response.json() if (response.ok) { setMessage(data.message) // Immediately update the local state to reflect the change const updateUserLockStatus = (users: UserData[]) => users.map((u) => (u.national_id === nationalId ? { ...u, lock_status: !currentLockStatus } : u)) setGlobalUsers((prev) => updateUserLockStatus(prev)) setTeamUsers((prev) => updateUserLockStatus(prev)) setDepartmentUsers((prev) => updateUserLockStatus(prev)) setFieldUsers((prev) => updateUserLockStatus(prev)) // Also refresh from server to ensure consistency setTimeout(() => { refetchGlobal() refetchTeam() refetchDepartment() refetchField() }, 100) } else { setMessage(data.error || "שגיאה בשינוי סטטוס נעילה") } } catch (err) { setMessage("שגיאה בחיבור לשרת") } } const getStatusText = (status?: string) => { switch (status) { case "yes": return { text: "במקלט/חדר מוגן", color: "text-green-600" } case "no": return { text: "לא במקלט", color: "text-orange-600" } case "no_alarm": return { text: "אין אזעקה", color: "text-blue-600" } case "safe_after_exit": return { text: "אני בטוח.ה (סוף אירוע)", color: "text-emerald-600" } default: return { text: "דיווח חסר", color: "text-gray-500" } } } const handleGlobalCategoryClick = (category: string, categoryName: string) => { setSelectedCategory(category) setSelectedCategoryName(categoryName) setModalOpen(true) } const handleTeamCategoryClick = (category: string, categoryName: string) => { setSelectedCategory(category) setSelectedCategoryName(categoryName) setTeamModalOpen(true) } const handleDepartmentCategoryClick = (category: string, categoryName: string) => { setSelectedCategory(category) setSelectedCategoryName(categoryName) setDepartmentModalOpen(true) } const handleFieldCategoryClick = (category: string, categoryName: string) => { setSelectedCategory(category) setSelectedCategoryName(categoryName) setFieldModalOpen(true) } const handleManualRefresh = async () => { setIsRefreshing(true) try { await Promise.all([refetchGlobal(), refetchTeam(), refetchDepartment(), refetchField()]) } catch (error) { console.error("Manual refresh failed:", error) setMessage("שגיאה ברענון הנתונים") } finally { setTimeout(() => setIsRefreshing(false), 500) } } const handleReportOnBehalf = async (userId: string, status: string) => { try { const response = await fetch("/api/admin/report-on-behalf", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ adminId: user?.national_id, targetUserId: userId, status, }), }) const data = await response.json() if (response.ok) { setMessage(data.message) refetchGlobal() refetchTeam() refetchDepartment() refetchField() } else { setMessage(data.error || "שגיאה בדיווח") } } catch (err) { setMessage("שגיאה בחיבור לשרת") } } const formatCooldownTime = (seconds: number) => { if (seconds <= 0) return "" const minutes = Math.floor(seconds / 60) const remainingSeconds = seconds % 60 if (minutes > 0) { return `${minutes}:${remainingSeconds.toString().padStart(2, "0")}` } return `${remainingSeconds} שניות` } const renderStatsSection = ( stats: Stats | null, onCategoryClick: (category: string, categoryName: string) => void, isTeam = false, customName?: string, ) => { const displayName = customName || (isTeam ? `צוות ${teamName}` : "כלליות") return (
{isTeam ? `צוות ${teamName}` : customName ? `מסגרת ${customName}` : "כללי"}{" "} {isRefreshing && } {(isTeam ? teamConnected : departmentConnected ? departmentConnected : fieldConnected ? fieldConnected : globalConnected) &&
}
{stats ? ( <> {viewMode === "list" ? (
onCategoryClick("no_report", "לא דיווחו")} > לא דיווחו: {stats.no_report}
onCategoryClick("in_shelter", "במקלט/חדר מוגן")} > במקלט: {stats.in_shelter}
onCategoryClick("not_in_shelter", "לא במקלט - אין מקלט בקרבת מקום")} > לא במקלט: {stats.not_in_shelter}
onCategoryClick("no_alarm", "אין אזעקה באזור")} > אין אזעקה: {stats.no_alarm}
onCategoryClick("safe_after_exit", "אני בטוח.ה (סוף אירוע)")} > אני בטוח.ה (סוף אירוע) {stats.safe_after_exit}
) : useSimpleChart ? ( ) : ( )} ) : (
טוען סטטיסטיקות...
)}
{( isTeam ? teamConnected : departmentConnected ? departmentConnected : fieldConnected ? fieldConnected : globalConnected ) ? ( ) : ( "מנסה להתחבר לעדכונים..." )}
) } const renderUsersTable = (users: UserData[], changedRows: Set, isReadOnly = false) => { return (
שם דיווח {!isReadOnly && פעולות} תחום מסגרת צוות {users.map((userData) => { const status = getStatusText(userData.in_shelter) const isChanged = changedRows.has(userData.national_id) const isLocked = userData.lock_status || false return ( {userData.name} {isChanged && 🔄} {status.text} {!isReadOnly && (
)} {userData.field || "לא הוגדר"} {userData.department || "לא הוגדר"} {userData.team || "לא הוגדר"}
) })}
{users.length === 0 &&
אין משתמשים
}
) } if (!user) return null return (
ניהול
{globalConnected || teamConnected || departmentConnected || fieldConnected ? ( <> מקוון ) : ( <> מתחבר... )}
{user?.role !== "user" && ( )}
{message && ( {message} )} {debugMode && ( Debug Info:
User: {user?.name} ({user?.role})
Team: {teamName}
Global Users: {globalUsers.length}
Global Connected: {globalConnected ? "Yes" : "No"}
Global Reset Cooldown: {globalResetCooldown} seconds
Team Reset Cooldown: {teamResetCooldown} seconds
Department Reset Cooldown: {departmentResetCooldown} seconds
Field Reset Cooldown: {fieldResetCooldown} seconds
)} צוות מסגרת תחום כללי
איפוס סטטוסי הצוות
הערה: איפוס יאפס רק את המשתמשים מהצוות שלך ({teamName}) שאינם נעולים
{renderStatsSection(teamStats, handleTeamCategoryClick, true)}
ניהול משתמשי צוות {teamName} {teamChangedRows.size > 0 && ( {teamChangedRows.size} עדכונים חדשים )} {loadingUsers ? (
טוען משתמשים...
) : ( renderUsersTable(teamUsers, teamChangedRows) )}
{user?.role === "team_admin" ? "צפייה במסגרת" : "איפוס סטטוסי המסגרת"} {user?.role === "team_admin" ? (

צפייה בלבד

כמנהל צוות, אתה יכול לראות את המסגרת שלך אך לא לאפס אותה

) : ( <>
הערה: איפוס יאפס את כל המשתמשים מהמסגרת שלך ({departmentName}) שאינם נעולים
)}
{renderStatsSection(departmentStats, handleDepartmentCategoryClick, false, departmentName)}
{user?.role === "team_admin" ? "צפייה במשתמשי מסגרת" : "ניהול משתמשי מסגרת"} {departmentName} {departmentChangedRows.size > 0 && ( {departmentChangedRows.size} עדכונים חדשים )} {loadingUsers ? (
טוען משתמשים...
) : ( renderUsersTable(departmentUsers, departmentChangedRows, user?.role === "team_admin") )}
איפוס סטטוסי התחום {(user?.role === "department_admin" || user?.role === "team_admin") ? (

צפייה בלבד

כ{ROLE_NAMES[user.role]}, אתה יכול לראות את התחום שלך אך לא לאפס אותו

) : ( <>
הערה: איפוס יאפס את כל המשתמשים מהתחום שלך ({fieldName}) שאינם נעולים
)}
{renderStatsSection(fieldStats, handleFieldCategoryClick, false, fieldName)}
{(user?.role === "team_admin" || user?.role === "department_admin") ? "צפייה במשתמשי תחום" : "ניהול משתמשי תחום"} {fieldName} {fieldChangedRows.size > 0 && ( {fieldChangedRows.size} עדכונים חדשים )} {loadingUsers ? (
טוען משתמשים...
) : ( renderUsersTable(fieldUsers, fieldChangedRows, (user?.role === "team_admin" || user?.role === "department_admin")) )}
איפוס סטטוסים כללי {globalLastReset &&

איפוס אחרון: {globalLastReset}

}
הערה: איפוס יאפס את כל המשתמשים במערכת (כולל מנהלים) שאינם נעולים
{renderStatsSection(globalStats, handleGlobalCategoryClick, false)}
הוספת משתמש חדש
setNewUser({ ...newUser, name: e.target.value })} placeholder="שם" required />
הערה: המשתמש יקבל את הסיסמה הזמנית "password123" ויידרש לשנותה בכניסה הראשונה
ניהול כל המשתמשים {changedRows.size > 0 && ( {changedRows.size} עדכונים חדשים )} {loadingUsers ? (
טוען משתמשים...
) : ( renderUsersTable(globalUsers, changedRows) )}
setModalOpen(false)} category={selectedCategory} categoryName={selectedCategoryName} /> setTeamModalOpen(false)} category={selectedCategory} categoryName={selectedCategoryName} adminId={user?.national_id || ""} teamName={teamName} /> setDepartmentModalOpen(false)} category={selectedCategory} categoryName={selectedCategoryName} adminId={user?.national_id || ""} departmentName={departmentName} /> setFieldModalOpen(false)} category={selectedCategory} categoryName={selectedCategoryName} adminId={user?.national_id || ""} fieldName={fieldName} /> setReportModalOpen(false)} user={selectedUserForReport} onReport={handleReportOnBehalf} /> {/* Hostname Footer */}
סביבה: {process.env.NEXT_PUBLIC_HOSTNAME || process.env.HOSTNAME || "לא זוהה"}
גרסה: {process.env.APPVERSION || "לא הוצהר ב-Dockerfile!"}
2025 COPYRIGHT TR-WEB
) }