Add Sensor Hub tab to account settings, integrating new SensorHubTab and related components for sensor management. Updated layout and added error handling in the sensor form.
This commit is contained in:
@@ -12,6 +12,7 @@ const SecurityTab = dynamic(() => import('@views/pages/account-settings/security
|
||||
const BillingPlansTab = dynamic(() => import('@views/pages/account-settings/billing-plans'))
|
||||
const NotificationsTab = dynamic(() => import('@views/pages/account-settings/notifications'))
|
||||
const ConnectionsTab = dynamic(() => import('@views/pages/account-settings/connections'))
|
||||
const SensorHubTab = dynamic(() => import('@views/pages/account-settings/sensor-hub'))
|
||||
|
||||
// Vars
|
||||
const tabContentList = (): { [key: string]: ReactElement } => ({
|
||||
@@ -19,7 +20,8 @@ const tabContentList = (): { [key: string]: ReactElement } => ({
|
||||
security: <SecurityTab />,
|
||||
'billing-plans': <BillingPlansTab />,
|
||||
notifications: <NotificationsTab />,
|
||||
connections: <ConnectionsTab />
|
||||
connections: <ConnectionsTab />,
|
||||
'sensor-hub': <SensorHubTab />
|
||||
})
|
||||
|
||||
const AccountSettingsPage = () => {
|
||||
|
||||
@@ -24,10 +24,11 @@ const AccountSettings = ({ tabContentList }: { tabContentList: { [key: string]:
|
||||
return (
|
||||
<TabContext value={activeTab}>
|
||||
<Grid container spacing={6}>
|
||||
{/* <Grid size={{ xs: 12 }}>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<CustomTabList onChange={handleChange} variant='scrollable' pill='true'>
|
||||
<Tab label='Account' icon={<i className='tabler-users' />} iconPosition='start' value='account' />
|
||||
<Tab label='Security' icon={<i className='tabler-lock' />} iconPosition='start' value='security' />
|
||||
<Tab label='SensorHub' icon={<i className='tabler-device-watch' />} iconPosition='start' value='sensor-hub' />
|
||||
{/* <Tab label='Security' icon={<i className='tabler-lock' />} iconPosition='start' value='security' />
|
||||
<Tab
|
||||
label='Billing & Plans'
|
||||
icon={<i className='tabler-bookmark' />}
|
||||
@@ -40,9 +41,9 @@ const AccountSettings = ({ tabContentList }: { tabContentList: { [key: string]:
|
||||
iconPosition='start'
|
||||
value='notifications'
|
||||
/>
|
||||
<Tab label='Connections' icon={<i className='tabler-link' />} iconPosition='start' value='connections' />
|
||||
<Tab label='Connections' icon={<i className='tabler-link' />} iconPosition='start' value='connections' /> */}
|
||||
</CustomTabList>
|
||||
</Grid> */}
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<TabPanel value={activeTab} className='p-0'>
|
||||
{tabContentList[activeTab]}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
'use client'
|
||||
|
||||
// React Imports
|
||||
import { useState } from 'react'
|
||||
|
||||
// MUI Imports
|
||||
import Grid from '@mui/material/Grid2'
|
||||
import Button from '@mui/material/Button'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Card from '@mui/material/Card'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import Fade from '@mui/material/Fade'
|
||||
|
||||
// Hook Imports
|
||||
import { useSensorHub } from '@/hooks/useSensorHub'
|
||||
|
||||
// API Imports
|
||||
import type { Sensor } from '@/libs/api/services/sensorHubService'
|
||||
|
||||
// Component Imports
|
||||
import SensorHubTable from '@views/sensorHub/SensorHubTable'
|
||||
import OptionSensorHub from '@views/sensorHub/OptionSensorHub'
|
||||
import FormSensorHub from '@views/sensorHub/FormSensorHub'
|
||||
|
||||
const transitionTimeout = { enter: 300, exit: 200 }
|
||||
|
||||
const SensorHubTabContent = () => {
|
||||
const [showAddForm, setShowAddForm] = useState(false)
|
||||
const { setSensorHub } = useSensorHub()
|
||||
|
||||
const handleBack = () => setShowAddForm(false)
|
||||
|
||||
const handleConfirm = (sensor: Sensor) => {
|
||||
setSensorHub({ id: sensor.uuid_sensor, ...sensor })
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid container spacing={6}>
|
||||
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Fade key={showAddForm ? 'form' : 'options'} in timeout={transitionTimeout}>
|
||||
<div>
|
||||
{showAddForm ? (
|
||||
<FormSensorHub onBack={handleBack} />
|
||||
) : (
|
||||
<div className='flex flex-col gap-4'>
|
||||
<div className='grid grid-cols-1 sm:grid-cols-[1fr_auto] items-center gap-4'>
|
||||
<div className='flex flex-col gap-0.5'>
|
||||
<Typography variant='h6' fontWeight={600}>
|
||||
انتخاب سنسور
|
||||
</Typography>
|
||||
<Typography variant='body2' color='text.secondary' sx={{ lineHeight: 1.5 }}>
|
||||
سنسور مورد نظر را انتخاب کنید یا سنسور جدید اضافه کنید
|
||||
</Typography>
|
||||
</div>
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
startIcon={<i className='tabler-plus text-xl' />}
|
||||
onClick={() => setShowAddForm(true)}
|
||||
>
|
||||
اضافه کردن سنسور
|
||||
</Button>
|
||||
</div>
|
||||
<OptionSensorHub onConfirm={handleConfirm} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Fade>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
export default SensorHubTabContent
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './SensorHubTabContent'
|
||||
@@ -6,7 +6,11 @@ import { useState } from 'react'
|
||||
// MUI Imports
|
||||
import Grid from '@mui/material/Grid2'
|
||||
import Button from '@mui/material/Button'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import Alert from '@mui/material/Alert'
|
||||
|
||||
// API Imports
|
||||
import { sensorHubService } from '@/libs/api'
|
||||
|
||||
// Component Imports
|
||||
import CustomTextField from '@core/components/mui/TextField'
|
||||
@@ -18,10 +22,22 @@ type FormSensorHubProps = {
|
||||
const FormSensorHub = ({ onBack }: FormSensorHubProps) => {
|
||||
const [name, setName] = useState('')
|
||||
const [uuidSensor, setUuidSensor] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
// TODO: Call API to add sensor
|
||||
setError(null)
|
||||
setLoading(true)
|
||||
try {
|
||||
await sensorHubService.addSensor({ name, uuid_sensor: uuidSensor })
|
||||
onBack()
|
||||
} catch (err: unknown) {
|
||||
const message = err && typeof err === 'object' && 'message' in err ? String((err as { message: string }).message) : 'خطا در ذخیره سنسور'
|
||||
setError(message)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -40,6 +56,13 @@ const FormSensorHub = ({ onBack }: FormSensorHubProps) => {
|
||||
</div>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Grid container spacing={4}>
|
||||
{error && (
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<Alert severity='error' onClose={() => setError(null)}>
|
||||
{error}
|
||||
</Alert>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<CustomTextField
|
||||
fullWidth
|
||||
@@ -59,11 +82,16 @@ const FormSensorHub = ({ onBack }: FormSensorHubProps) => {
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12 }} className='flex gap-2'>
|
||||
<Button variant='tonal' color='secondary' onClick={onBack}>
|
||||
<Button variant='tonal' color='secondary' onClick={onBack} disabled={loading}>
|
||||
انصراف
|
||||
</Button>
|
||||
<Button variant='contained' type='submit' startIcon={<i className='tabler-plus' />}>
|
||||
ذخیره سنسور
|
||||
<Button
|
||||
variant='contained'
|
||||
type='submit'
|
||||
disabled={loading}
|
||||
startIcon={loading ? <CircularProgress size={16} color='inherit' /> : <i className='tabler-plus' />}
|
||||
>
|
||||
{loading ? 'در حال ذخیره...' : 'ذخیره سنسور'}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user