CI/CD
This commit is contained in:
@@ -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<User[]>([])
|
||||
const [users, setUsers] = useState<UsersType[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(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 || 'خطا در دریافت لیست کاربران')
|
||||
|
||||
@@ -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<typeof useReactTable> }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const TablePaginationComponent = ({ table }: { table: Table<any> }) => {
|
||||
return (
|
||||
<div className='flex justify-between items-center flex-wrap pli-6 border-bs bs-auto plb-[12.5px] gap-2'>
|
||||
<Typography color='text.disabled'>
|
||||
|
||||
+2
-1
@@ -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<string, unknown>
|
||||
messages: faMessages as AbstractIntlMessages
|
||||
}
|
||||
})
|
||||
|
||||
+25
-4
@@ -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'
|
||||
|
||||
@@ -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<ApiResponse<{ users: User[]; stats: { total: number; active: number; pending: number; inactive: number } }>>('/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<UserDetails> {
|
||||
const response = await apiClient.get<ApiResponse<UserDetails>>(`/api/account/${id}/`)
|
||||
|
||||
return response.data as unknown as UserDetails
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete a user by ID
|
||||
*/
|
||||
async deleteUser(id: number): Promise<void> {
|
||||
await apiClient.delete<ApiResponse<unknown>>(`/api/account/${id}/`)
|
||||
},
|
||||
|
||||
/**
|
||||
* Update current user profile (first_name, last_name, email)
|
||||
*/
|
||||
|
||||
@@ -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<DateObject | undefined>(() => {
|
||||
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 (
|
||||
<Box
|
||||
@@ -87,9 +87,9 @@ const AppJalaliDatepicker = (props: AppJalaliDatepickerProps) => {
|
||||
>
|
||||
<Calendar
|
||||
value={displayValue}
|
||||
onChange={handleChange}
|
||||
onChange={handleChange as any}
|
||||
calendar={persian}
|
||||
locale={fa}
|
||||
locale={persian_fa}
|
||||
className="teal"
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -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: 'امروز',
|
||||
|
||||
@@ -44,7 +44,7 @@ const FarmDashboardSettingsDrawer = (props: FarmDashboardSettingsDrawerProps) =>
|
||||
<Drawer
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
anchor='end'
|
||||
anchor='right'
|
||||
variant='temporary'
|
||||
ModalProps={{
|
||||
disablePortal: true,
|
||||
|
||||
@@ -54,7 +54,7 @@ const cardRowSx = {
|
||||
'& > *': { flex: 1, minHeight: 0 }
|
||||
}
|
||||
|
||||
const CARD_COMPONENTS: Record<CardId, React.ComponentType> = {
|
||||
const CARD_COMPONENTS: Record<CardId, React.ComponentType<{ data?: Record<string, unknown> }>> = {
|
||||
farmOverviewKpis: FarmOverviewKPIs,
|
||||
farmWeatherCard: FarmWeatherCard,
|
||||
farmAlertsTracker: FarmAlertsTracker,
|
||||
|
||||
@@ -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'
|
||||
/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -128,7 +128,7 @@ export default function CropZoningWeatherSection() {
|
||||
</Typography>
|
||||
<Typography variant='h5'>
|
||||
{temp}
|
||||
{weatherData.unit ?? '°C'}
|
||||
{(weatherData.unit as string) ?? '°C'}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -67,7 +67,7 @@ export default function ZoneDetailPanel({
|
||||
<Drawer
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
anchor='end'
|
||||
anchor='right'
|
||||
variant='temporary'
|
||||
ModalProps={{
|
||||
disablePortal: true,
|
||||
|
||||
@@ -68,11 +68,11 @@ export const CARD_GRID_SIZE: Record<CardId, { xs?: number; sm?: number; md?: num
|
||||
farmAlertsTimeline: { xs: 12, lg: 4 },
|
||||
waterNeedPrediction: { xs: 12, lg: 8 },
|
||||
harvestPredictionCard: { xs: 12, md: 6, lg: 4 },
|
||||
yieldPredictionChart: { xs: 12 },
|
||||
soilMoistureHeatmap: { xs: 12 },
|
||||
yieldPredictionChart: { xs: 12, lg: 12 },
|
||||
soilMoistureHeatmap: { xs: 12, lg: 12 },
|
||||
ndviHealthCard: { xs: 12, md: 6, lg: 4 },
|
||||
recommendationsList: { xs: 12, md: 6, lg: 8 },
|
||||
economicOverview: { xs: 12 }
|
||||
economicOverview: { xs: 12, lg: 12 }
|
||||
}
|
||||
|
||||
/** Display label for each card (for settings UI) */
|
||||
|
||||
@@ -29,7 +29,7 @@ type OptionSensorHubProps = {
|
||||
const formatLastUpdated = (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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user