diff --git a/src/app/(dashboard)/(private)/apps/user/list/page.tsx b/src/app/(dashboard)/(private)/apps/user/list/page.tsx index 705c78b..32f010b 100644 --- a/src/app/(dashboard)/(private)/apps/user/list/page.tsx +++ b/src/app/(dashboard)/(private)/apps/user/list/page.tsx @@ -13,10 +13,10 @@ import UserList from '@views/apps/user/list' // API Imports import { userManagementService } from '@/libs/api' -import type { User } from '@/libs/api/services/userManagementService' +import type { UsersType } from '@/types/apps/userTypes' const UserListApp = () => { - const [users, setUsers] = useState([]) + const [users, setUsers] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) @@ -24,7 +24,7 @@ const UserListApp = () => { const fetchUsers = async () => { try { setLoading(true) - const response = await userManagementService.getUsers() + const response = await userManagementService.getUsers() as any setUsers(response.users) } catch (err: any) { setError(err.message || 'خطا در دریافت لیست کاربران') diff --git a/src/components/TablePaginationComponent.tsx b/src/components/TablePaginationComponent.tsx index 33fe4e8..70c60ef 100644 --- a/src/components/TablePaginationComponent.tsx +++ b/src/components/TablePaginationComponent.tsx @@ -3,9 +3,10 @@ import Pagination from '@mui/material/Pagination' import Typography from '@mui/material/Typography' // Third Party Imports -import type { useReactTable } from '@tanstack/react-table' +import type { Table } from '@tanstack/react-table' -const TablePaginationComponent = ({ table }: { table: ReturnType }) => { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const TablePaginationComponent = ({ table }: { table: Table }) => { return (
diff --git a/src/i18n/request.ts b/src/i18n/request.ts index e17339a..d09a099 100644 --- a/src/i18n/request.ts +++ b/src/i18n/request.ts @@ -1,4 +1,5 @@ import { getRequestConfig } from 'next-intl/server' +import type { AbstractIntlMessages } from 'next-intl' import faMessages from '../../messages/fa.json' export default getRequestConfig(async () => { @@ -6,6 +7,6 @@ export default getRequestConfig(async () => { return { locale, - messages: faMessages as Record + messages: faMessages as AbstractIntlMessages } }) diff --git a/src/libs/api/index.ts b/src/libs/api/index.ts index 47e1364..ffe49e8 100644 --- a/src/libs/api/index.ts +++ b/src/libs/api/index.ts @@ -4,7 +4,16 @@ export * from './client' export * from './types' -export * from './services/authService' +export { + type RequestOTPRequest, + type RequestOTPResponse, + type VerifyOTPRequest, + type AuthUser, + type VerifyOTPResponse, + type UpdateProfilePayload, + type UpdateProfileResponse, + authService +} from './services/authService' export * from './services/taskService' export * from './services/eventService' export * from './services/simulatorService' @@ -12,8 +21,20 @@ export * from './services/chatService' export * from './services/aiChatService' export * from './services/kanbanService' export * from './services/todoService' -export * from './services/userManagementService' +export { + type User, + type UserDetails, + type Account, + type ApiResponse, + type UpdateProfileRequest, + type AddAccountRequest, + type UpdateAccountRequest, + userManagementService +} from './services/userManagementService' export * from './services/rolesPermissionsService' export * from './services/sensorHubService' -export * from './services/farmDashboardService' - +export { + type FarmDashboardConfigResponse, + type FarmDashboardCardsResponse, + farmDashboardService +} from './services/farmDashboardService' diff --git a/src/libs/api/services/userManagementService.ts b/src/libs/api/services/userManagementService.ts index d174f88..36d6fcf 100644 --- a/src/libs/api/services/userManagementService.ts +++ b/src/libs/api/services/userManagementService.ts @@ -6,6 +6,36 @@ import { apiClient } from '../client' +export interface User { + id: number + username: string + email: string + first_name: string + last_name: string + phone_number: string + role?: string + status?: string + avatar?: string + fullName?: string + currentPlan?: string + billing?: string + company?: string + country?: string + contact?: string +} + +export interface UserDetails { + id: number + username: string + email: string + first_name: string + last_name: string + phone_number: string + role?: string + status?: string + avatar?: string +} + export interface Account { id: number username: string @@ -49,6 +79,31 @@ export interface UpdateAccountRequest { } export const userManagementService = { + /** + * Get list of users + */ + async getUsers(): Promise<{ users: User[]; stats: { total: number; active: number; pending: number; inactive: number } }> { + const response = await apiClient.get>('/api/account/') + + return response.data as { users: User[]; stats: { total: number; active: number; pending: number; inactive: number } } + }, + + /** + * Get a single user by ID + */ + async getUser(id: number): Promise { + const response = await apiClient.get>(`/api/account/${id}/`) + + return response.data as unknown as UserDetails + }, + + /** + * Delete a user by ID + */ + async deleteUser(id: number): Promise { + await apiClient.delete>(`/api/account/${id}/`) + }, + /** * Update current user profile (first_name, last_name, email) */ diff --git a/src/libs/styles/AppJalaliDatepicker.tsx b/src/libs/styles/AppJalaliDatepicker.tsx index b83e508..f02081f 100644 --- a/src/libs/styles/AppJalaliDatepicker.tsx +++ b/src/libs/styles/AppJalaliDatepicker.tsx @@ -10,9 +10,9 @@ import type { BoxProps } from '@mui/material/Box' // Third-party Imports import { Calendar } from 'react-multi-date-picker' -import type { DateObject } from 'react-multi-date-picker' +import DateObject from 'react-date-object' import persian from 'react-date-object/calendars/persian' -import fa from 'react-date-object/locales/fa' +import persian_fa from 'react-date-object/locales/persian_fa' // Styles - base styles only, we override colors via sx import 'react-multi-date-picker/styles/colors/teal.css' @@ -30,23 +30,23 @@ const AppJalaliDatepicker = (props: AppJalaliDatepickerProps) => { const [internalValue, setInternalValue] = useState(() => { const d = externalValue ?? new Date() - return new DateObject(d, { calendar: persian, locale: fa }) + return new DateObject({ date: d, calendar: persian, locale: persian_fa }) }) useEffect(() => { if (externalValue != null) { - setInternalValue(new DateObject(externalValue, { calendar: persian, locale: fa })) + setInternalValue(new DateObject({ date: externalValue, calendar: persian, locale: persian_fa })) } }, [externalValue]) const handleChange = (d: DateObject | null) => { if (d) { - setInternalValue(d) + setInternalValue(d as unknown as DateObject) onChange?.(d.toDate()) } } - const displayValue = internalValue ?? new DateObject({ calendar: persian, locale: fa }) + const displayValue = internalValue ?? new DateObject({ calendar: persian, locale: persian_fa }) return ( { > diff --git a/src/views/apps/calendar/Calendar.tsx b/src/views/apps/calendar/Calendar.tsx index b7cba4f..2647725 100644 --- a/src/views/apps/calendar/Calendar.tsx +++ b/src/views/apps/calendar/Calendar.tsx @@ -83,7 +83,7 @@ const Calendar = (props: CalenderProps) => { }, views: { week: { - titleFormat(arg) { + titleFormat(arg: any) { const start = arg.start const end = arg.end @@ -94,20 +94,21 @@ const Calendar = (props: CalenderProps) => { }) if (!start && !end) { - return { text: '' } + return '' } if (start && !end) { - return { text: formatter.format(start) } + return formatter.format(start instanceof Date ? start : new Date(start.marker ?? start)) } if (!start && end) { - return { text: formatter.format(end) } + return formatter.format(end instanceof Date ? end : new Date(end.marker ?? end)) } - return { - text: `${formatter.format(start)} - ${formatter.format(end)}` - } + const s = start instanceof Date ? start : new Date(start.marker ?? start) + const e = end instanceof Date ? end : new Date(end.marker ?? end) + + return `${formatter.format(s)} - ${formatter.format(e)}` } } }, @@ -116,7 +117,7 @@ const Calendar = (props: CalenderProps) => { return formatter.format(arg.date) }, - titleFormat(arg) { + titleFormat(arg: any) { const { start, end } = arg const monthFormatter = new Intl.DateTimeFormat('fa-IR-u-ca-persian', { @@ -129,18 +130,16 @@ const Calendar = (props: CalenderProps) => { const target = start || end if (!target) { - return { text: '' } + return '' } const asDate = target instanceof Date ? target : new Date(target as any) if (Number.isNaN(asDate.getTime())) { - return { text: '' } + return '' } - return { - text: monthFormatter.format(asDate) - } + return monthFormatter.format(asDate) }, buttonText: { today: 'امروز', diff --git a/src/views/dashboards/farm/FarmDashboardSettingsDrawer.tsx b/src/views/dashboards/farm/FarmDashboardSettingsDrawer.tsx index ef033ce..eb79daa 100644 --- a/src/views/dashboards/farm/FarmDashboardSettingsDrawer.tsx +++ b/src/views/dashboards/farm/FarmDashboardSettingsDrawer.tsx @@ -44,7 +44,7 @@ const FarmDashboardSettingsDrawer = (props: FarmDashboardSettingsDrawerProps) => *': { flex: 1, minHeight: 0 } } -const CARD_COMPONENTS: Record = { +const CARD_COMPONENTS: Record }>> = { farmOverviewKpis: FarmOverviewKPIs, farmWeatherCard: FarmWeatherCard, farmAlertsTracker: FarmAlertsTracker, diff --git a/src/views/dashboards/farm/FarmOverviewKPIs.tsx b/src/views/dashboards/farm/FarmOverviewKPIs.tsx index 5b01e76..7da7c5c 100644 --- a/src/views/dashboards/farm/FarmOverviewKPIs.tsx +++ b/src/views/dashboards/farm/FarmOverviewKPIs.tsx @@ -37,7 +37,7 @@ const FarmOverviewKPIs = ({ data }: FarmOverviewKPIsProps) => { avatarIcon={kpi.avatarIcon ?? 'tabler-chart-bar'} avatarSkin='light' avatarSize={44} - chipText={kpi.chipText} + chipText={kpi.chipText ?? ''} chipColor={(kpi.chipColor as 'success' | 'warning') ?? 'success'} chipVariant='tonal' /> diff --git a/src/views/dashboards/farm/FarmWeatherCard.tsx b/src/views/dashboards/farm/FarmWeatherCard.tsx index 5081edd..763f7c8 100644 --- a/src/views/dashboards/farm/FarmWeatherCard.tsx +++ b/src/views/dashboards/farm/FarmWeatherCard.tsx @@ -26,10 +26,10 @@ interface FarmWeatherCardProps { const FarmWeatherCard = ({ data }: FarmWeatherCardProps) => { const t = useTranslations('farmDashboard') - const temperature = data?.temperature ?? 24 + const temperature = (data?.temperature as number | undefined) ?? 24 const condition = (data?.condition as string) ?? '' - const humidity = data?.humidity ?? 45 - const windSpeed = data?.windSpeed ?? 12 + const humidity = (data?.humidity as number | undefined) ?? 45 + const windSpeed = (data?.windSpeed as number | undefined) ?? 12 const windUnit = (data?.windUnit as string) ?? 'km/h' const unit = (data?.unit as string) ?? '°C' const chartData = data?.chartData as { labels?: string[]; series?: number[][] } | undefined diff --git a/src/views/dashboards/farm/SensorComparisonChart.tsx b/src/views/dashboards/farm/SensorComparisonChart.tsx index ae8b544..1ab2116 100644 --- a/src/views/dashboards/farm/SensorComparisonChart.tsx +++ b/src/views/dashboards/farm/SensorComparisonChart.tsx @@ -27,7 +27,7 @@ const SensorComparisonChart = ({ data }: SensorComparisonChartProps) => { const categories = (data?.categories as string[]) ?? [t('fallback.mon'), t('fallback.tue'), t('fallback.wed'), t('fallback.thu'), t('fallback.fri'), t('fallback.sat'), t('fallback.sun')] - const currentValue = data?.currentValue ?? 48 + const currentValue = (data?.currentValue as number | undefined) ?? 48 const vsLastWeek = (data?.vsLastWeek as string) ?? t('fallback.plusPercentVsLastWeek', { val: '5' }) const theme = useTheme() if (series.length === 0) return null diff --git a/src/views/dashboards/farm/cropZoning/CropZoningWeatherSection.tsx b/src/views/dashboards/farm/cropZoning/CropZoningWeatherSection.tsx index 90d6d49..43738f2 100644 --- a/src/views/dashboards/farm/cropZoning/CropZoningWeatherSection.tsx +++ b/src/views/dashboards/farm/cropZoning/CropZoningWeatherSection.tsx @@ -128,7 +128,7 @@ export default function CropZoningWeatherSection() { {temp} - {weatherData.unit ?? '°C'} + {(weatherData.unit as string) ?? '°C'} diff --git a/src/views/dashboards/farm/cropZoning/ZoneDetailPanel.tsx b/src/views/dashboards/farm/cropZoning/ZoneDetailPanel.tsx index 3e412ec..0bcf2a6 100644 --- a/src/views/dashboards/farm/cropZoning/ZoneDetailPanel.tsx +++ b/src/views/dashboards/farm/cropZoning/ZoneDetailPanel.tsx @@ -67,7 +67,7 @@ export default function ZoneDetailPanel({ { if (!dateStr) return '—' try { - const d = new DateObject(new Date(dateStr)).convert('persian').setLocale('fa') + const d = new DateObject(new Date(dateStr)).convert('persian' as any).setLocale('fa' as any) return d.format('YYYY/MM/DD') } catch { diff --git a/src/views/sensorHub/SensorHubTable.tsx b/src/views/sensorHub/SensorHubTable.tsx index 9bee843..6da8f3f 100644 --- a/src/views/sensorHub/SensorHubTable.tsx +++ b/src/views/sensorHub/SensorHubTable.tsx @@ -23,7 +23,7 @@ import styles from '@core/styles/table.module.css' const formatToShamsi = (dateStr: string | null | undefined): string => { if (!dateStr) return '—' try { - const d = new DateObject(new Date(dateStr)).convert('persian').setLocale('fa') + const d = new DateObject(new Date(dateStr)).convert('persian' as any).setLocale('fa' as any) return d.format('YYYY/MM/DD') } catch {