Feature/abniye fani
This commit is contained in:
@@ -37,7 +37,7 @@ const createCustomIcon = (size, iconUrl, labelText, color) => {
|
||||
};
|
||||
const MAX_ZOOM_FOR_MARKER = 13;
|
||||
|
||||
const MapInteraction = ({ setValue, startLat, startLng }) => {
|
||||
const MapInteraction = ({ setValue, startLat, startLng, title }) => {
|
||||
const [isMarkerLocked, setIsMarkerLocked] = useState(!!(startLat && startLng));
|
||||
const [enableSend, setEnableSend] = useState(false);
|
||||
const [startIconColor, setStartIconColor] = useState(startLat ? "#1CAC66" : "#003d4f");
|
||||
@@ -109,7 +109,7 @@ const MapInteraction = ({ setValue, startLat, startLng }) => {
|
||||
>
|
||||
<Zoom in={!enableSend}>
|
||||
<Alert sx={{ mt: 1, py: 0.5, px: 2, borderRadius: 2, border: 1 }} icon={false} color={"warning"}>
|
||||
برای ثبت محل فعالیت، لطفاً نقشه را بیشتر زوم کنید.
|
||||
{title}
|
||||
</Alert>
|
||||
</Zoom>
|
||||
</Stack>
|
||||
@@ -131,7 +131,12 @@ const MapInteraction = ({ setValue, startLat, startLng }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const MapInfoOneMarker = ({ setValue, errors, StartPoint = null }) => {
|
||||
const MapInfoOneMarker = ({
|
||||
setValue,
|
||||
errors,
|
||||
StartPoint = null,
|
||||
title = "برای ثبت محل فعالیت، لطفاً نقشه را بیشتر زوم کنید.",
|
||||
}) => {
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ width: "100%", height: "400px", marginBottom: "16px" }}>
|
||||
@@ -140,6 +145,7 @@ const MapInfoOneMarker = ({ setValue, errors, StartPoint = null }) => {
|
||||
setValue={setValue}
|
||||
startLat={StartPoint ? StartPoint.lat : null}
|
||||
startLng={StartPoint ? StartPoint.lng : null}
|
||||
title={title}
|
||||
/>
|
||||
</MapLayer>
|
||||
</Box>
|
||||
|
||||
@@ -8,67 +8,69 @@ import moment from "jalali-moment";
|
||||
|
||||
function MuiDatePicker({ value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error, label }) {
|
||||
return (
|
||||
<Box sx={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<MobileDatePicker
|
||||
value={value ? new Date(value) : null}
|
||||
sx={{ width: "100%" }}
|
||||
id={name}
|
||||
name={name}
|
||||
closeOnSelect
|
||||
disableFuture
|
||||
label={label}
|
||||
aria-describedby="component-helper-text"
|
||||
onChange={(value) => {
|
||||
const date = new Date(value);
|
||||
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD");
|
||||
setFieldValue(name, formattedDate);
|
||||
}}
|
||||
minDate={minDate ? new Date(minDate) : null}
|
||||
maxDate={maxDate ? new Date(maxDate) : null}
|
||||
slotProps={{
|
||||
textField: {
|
||||
error: error,
|
||||
size: "small",
|
||||
placeholder: placeholder,
|
||||
InputLabelProps: {
|
||||
shrink: true,
|
||||
<>
|
||||
<Box sx={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<MobileDatePicker
|
||||
value={value ? new Date(value) : null}
|
||||
sx={{ width: "100%" }}
|
||||
id={name}
|
||||
name={name}
|
||||
closeOnSelect
|
||||
disableFuture
|
||||
label={label}
|
||||
aria-describedby="component-helper-text"
|
||||
onChange={(value) => {
|
||||
const date = new Date(value);
|
||||
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD");
|
||||
setFieldValue(name, formattedDate);
|
||||
}}
|
||||
minDate={minDate ? new Date(minDate) : null}
|
||||
maxDate={maxDate ? new Date(maxDate) : null}
|
||||
slotProps={{
|
||||
textField: {
|
||||
error: error,
|
||||
size: "small",
|
||||
placeholder: placeholder,
|
||||
InputLabelProps: {
|
||||
shrink: true,
|
||||
},
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setFieldValue(name, "");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setFieldValue(name, "");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
{helperText ? (
|
||||
<FormHelperText id="component-helper-text" sx={{ color: error ? "#d32f2f" : "unset" }}>
|
||||
{helperText}
|
||||
</FormHelperText>
|
||||
) : null}
|
||||
</LocalizationProvider>
|
||||
</Box>
|
||||
}}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Box>
|
||||
{helperText && (
|
||||
<FormHelperText id="component-helper-text" sx={{ color: error ? "#d32f2f" : "unset", ml: 2 }}>
|
||||
{helperText}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,66 +13,68 @@ function MuiTimePicker({ value, setFieldValue, name, minTime, maxTime, helperTex
|
||||
const parsedMaxTime = maxTime || null;
|
||||
|
||||
return (
|
||||
<Box sx={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<MobileTimePicker
|
||||
value={parsedValue}
|
||||
sx={{ width: "100%" }}
|
||||
id={name}
|
||||
closeOnSelect
|
||||
label={label}
|
||||
ampm={false}
|
||||
timeSteps={{ hours: 1, minutes: 5 }}
|
||||
views={["hours", "minutes"]}
|
||||
name={name}
|
||||
onChange={(newValue) => {
|
||||
setFieldValue(name, newValue);
|
||||
}}
|
||||
minTime={parsedMinTime}
|
||||
maxTime={parsedMaxTime}
|
||||
slotProps={{
|
||||
textField: {
|
||||
placeholder: placeholder,
|
||||
size: "small",
|
||||
error: error,
|
||||
InputLabelProps: {
|
||||
shrink: true,
|
||||
<>
|
||||
<Box sx={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}>
|
||||
<LocalizationProvider
|
||||
dateAdapter={AdapterDateFnsJalali}
|
||||
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
|
||||
>
|
||||
<MobileTimePicker
|
||||
value={parsedValue}
|
||||
sx={{ width: "100%" }}
|
||||
id={name}
|
||||
closeOnSelect
|
||||
label={label}
|
||||
ampm={false}
|
||||
timeSteps={{ hours: 1, minutes: 5 }}
|
||||
views={["hours", "minutes"]}
|
||||
name={name}
|
||||
onChange={(newValue) => {
|
||||
setFieldValue(name, newValue);
|
||||
}}
|
||||
minTime={parsedMinTime}
|
||||
maxTime={parsedMaxTime}
|
||||
slotProps={{
|
||||
textField: {
|
||||
placeholder: placeholder,
|
||||
size: "small",
|
||||
error: error,
|
||||
InputLabelProps: {
|
||||
shrink: true,
|
||||
},
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setFieldValue(name, "");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setFieldValue(name, "");
|
||||
}}
|
||||
sx={{
|
||||
color: "#bfbfbf",
|
||||
"&:hover": {
|
||||
backgroundColor: "rgba(189, 189, 189, 0.1)",
|
||||
color: "#363434",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
{helperText ? (
|
||||
<FormHelperText id="component-helper-text" sx={{ color: error ? "#d32f2f" : "unset" }}>
|
||||
{helperText}
|
||||
</FormHelperText>
|
||||
) : null}
|
||||
</LocalizationProvider>
|
||||
</Box>
|
||||
}}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Box>
|
||||
{helperText && (
|
||||
<FormHelperText id="component-helper-text" sx={{ color: error ? "#d32f2f" : "unset", ml: 2 }}>
|
||||
{helperText}
|
||||
</FormHelperText>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
197
src/core/components/PlateNumber.jsx
Normal file
197
src/core/components/PlateNumber.jsx
Normal file
@@ -0,0 +1,197 @@
|
||||
import { Box, Button, Drawer, FormHelperText, Stack, TextField } from "@mui/material";
|
||||
import AccessibleIcon from "@mui/icons-material/Accessible";
|
||||
import { Controller, useFormState, useWatch } from "react-hook-form";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const plate_words = [
|
||||
{ id: 1, value: "الف", name: "الف" },
|
||||
{ id: 2, value: "ب", name: "ب" },
|
||||
{ id: 3, value: "پ", name: "پ" },
|
||||
{ id: 4, value: "ت", name: "ت" },
|
||||
{ id: 5, value: "ث", name: "ث" },
|
||||
{ id: 6, value: "ج", name: "ج" },
|
||||
{ id: 7, value: "د", name: "د" },
|
||||
{ id: 8, value: "ز", name: "ز" },
|
||||
{ id: 9, value: "س", name: "س" },
|
||||
{ id: 10, value: "ش", name: "ش" },
|
||||
{ id: 11, value: "ص", name: "ص" },
|
||||
{ id: 12, value: "ط", name: "ط" },
|
||||
{ id: 13, value: "ع", name: "ع" },
|
||||
{ id: 14, value: "ف", name: "ف" },
|
||||
{ id: 15, value: "ق", name: "ق" },
|
||||
{ id: 16, value: "ک", name: "گ" },
|
||||
{ id: 17, value: "ل", name: "ل" },
|
||||
{ id: 18, value: "م", name: "م" },
|
||||
{ id: 19, value: "ن", name: "ن" },
|
||||
{ id: 20, value: "و", name: "و" },
|
||||
{ id: 21, value: "ه", name: "ه" },
|
||||
{ id: 22, value: "ی", name: "ی" },
|
||||
{ id: 23, value: "*", name: <AccessibleIcon /> },
|
||||
];
|
||||
|
||||
const PlateNumber = ({ control }) => {
|
||||
const platePart2 = useWatch({ control, name: "plate_part2" });
|
||||
const [plateDrawer, setPlateDrawer] = useState(false);
|
||||
const { errors } = useFormState({ control });
|
||||
const plateErrors = ["plate_part1", "plate_part2", "plate_part3", "plate_part4"].some((part) => errors[part]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
border: 1,
|
||||
borderColor: plateErrors ? "error.main" : "divider",
|
||||
overflow: "hidden",
|
||||
borderRadius: 1,
|
||||
}}
|
||||
>
|
||||
<Controller
|
||||
name="plate_part4"
|
||||
control={control}
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
type="tel"
|
||||
inputProps={{
|
||||
inputMode: "number",
|
||||
min: 0,
|
||||
pattern: "[0-9]*",
|
||||
sx: { textAlign: "center" },
|
||||
}}
|
||||
onChange={(event) => {
|
||||
const inputValue = event.target.value;
|
||||
if (isNaN(Number(inputValue))) {
|
||||
return;
|
||||
}
|
||||
inputValue.length <= 2 ? field.onChange(inputValue) : null;
|
||||
}}
|
||||
size="small"
|
||||
placeholder="xx"
|
||||
sx={{ flexGrow: 2, "& fieldset": { border: "none" } }}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="plate_part3"
|
||||
control={control}
|
||||
defaultValue=""
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
type="tel"
|
||||
inputProps={{
|
||||
inputMode: "number",
|
||||
min: 0,
|
||||
pattern: "[0-9]*",
|
||||
sx: { textAlign: "center" },
|
||||
}}
|
||||
onChange={(event) => {
|
||||
const inputValue = event.target.value;
|
||||
if (isNaN(Number(inputValue))) {
|
||||
return;
|
||||
}
|
||||
inputValue.length <= 3 ? field.onChange(inputValue) : null;
|
||||
}}
|
||||
size="small"
|
||||
placeholder="xxx"
|
||||
sx={{
|
||||
flexGrow: 3,
|
||||
borderLeft: 1,
|
||||
borderRadius: 0,
|
||||
borderColor: "divider",
|
||||
"& fieldset": { border: "none" },
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Box sx={{ flexGrow: 1 }}>
|
||||
<Button
|
||||
onClick={() => setPlateDrawer(true)}
|
||||
sx={{ height: "100%", borderRadius: 0, borderColor: "divider" }}
|
||||
size={"small"}
|
||||
>
|
||||
{plate_words.find((p) => p.value === platePart2)?.name || "الف"}
|
||||
</Button>
|
||||
</Box>
|
||||
<Drawer
|
||||
sx={{ zIndex: 9999 }}
|
||||
anchor={"bottom"}
|
||||
open={plateDrawer}
|
||||
onClose={() => setPlateDrawer(false)}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
mx: "auto",
|
||||
my: 2,
|
||||
gap: 2,
|
||||
width: "60%",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{plate_words.map((item) => (
|
||||
<Controller
|
||||
key={item.id}
|
||||
name="plate_part2"
|
||||
control={control}
|
||||
defaultValue=""
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<Button
|
||||
onClick={() => {
|
||||
setPlateDrawer(false);
|
||||
field.onChange(item.value);
|
||||
}}
|
||||
sx={{ width: "fit-content" }}
|
||||
variant="contained"
|
||||
>
|
||||
{item.name}
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
</Drawer>
|
||||
<Controller
|
||||
name="plate_part1"
|
||||
control={control}
|
||||
defaultValue=""
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
type="tel"
|
||||
size="small"
|
||||
placeholder="xx"
|
||||
sx={{ flexGrow: 2, "& fieldset": { border: "none" } }}
|
||||
inputProps={{
|
||||
inputMode: "number",
|
||||
min: 0,
|
||||
pattern: "[0-9]*",
|
||||
sx: { textAlign: "center" },
|
||||
}}
|
||||
onChange={(event) => {
|
||||
const inputValue = event.target.value;
|
||||
if (isNaN(Number(inputValue))) {
|
||||
return;
|
||||
}
|
||||
inputValue.length <= 2 ? field.onChange(inputValue) : null;
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Stack sx={{ width: 24, borderLeft: 1, borderColor: "divider" }}>
|
||||
<Box sx={{ flexGrow: 1, bgcolor: "#1ebc1e" }}></Box>
|
||||
<Box sx={{ flexGrow: 1, bgcolor: "white" }}></Box>
|
||||
<Box sx={{ flexGrow: 1, bgcolor: "#f52121" }}></Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
{plateErrors && (
|
||||
<FormHelperText sx={{ ml: 2 }} error>
|
||||
پلاک نامعتبر است!!!
|
||||
</FormHelperText>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default PlateNumber;
|
||||
49
src/core/components/SelectBox.jsx
Normal file
49
src/core/components/SelectBox.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { FormControl, FormHelperText, InputLabel, MenuItem, Select } from "@mui/material";
|
||||
|
||||
function SelectBox({
|
||||
name,
|
||||
value,
|
||||
onChange,
|
||||
onBlur,
|
||||
selectors,
|
||||
label,
|
||||
error,
|
||||
schema,
|
||||
disabled,
|
||||
helperText,
|
||||
isLoading,
|
||||
errorEcured,
|
||||
variant = "outlined",
|
||||
}) {
|
||||
return (
|
||||
<FormControl disabled={disabled || false} fullWidth variant={variant} size="small" error={!!error}>
|
||||
<InputLabel>{label}</InputLabel>
|
||||
<Select
|
||||
label={label}
|
||||
name={name}
|
||||
size="small"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
onBlur={onBlur}
|
||||
>
|
||||
{isLoading ? (
|
||||
<MenuItem sx={{ color: "primary.main" }}>درحال دریافت اطلاعات...</MenuItem>
|
||||
) : errorEcured ? (
|
||||
<MenuItem sx={{ color: "secondary.main" }}>خطا در دریافت اطلاعات!!!</MenuItem>
|
||||
) : (
|
||||
selectors.map((selector) => {
|
||||
return (
|
||||
<MenuItem key={selector.id} value={selector[schema.value]}>
|
||||
{selector[schema.name]}
|
||||
</MenuItem>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</Select>
|
||||
<FormHelperText>{helperText || error?.message}</FormHelperText>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
export default SelectBox;
|
||||
@@ -14,7 +14,6 @@ const ShowPlak = ({ plak_number }) => {
|
||||
};
|
||||
};
|
||||
const plakParts = processPlak(plak_number);
|
||||
|
||||
return (
|
||||
<Stack sx={{ border: 1, borderColor: "divider", borderRadius: 1 }} direction={"row"}>
|
||||
<Stack
|
||||
|
||||
@@ -468,7 +468,7 @@ export const pageMenu = [
|
||||
id: "receiptManagmentOparationCartable",
|
||||
label: "کارتابل",
|
||||
type: "page",
|
||||
route: process.env.NEXT_PUBLIC_API_URL + "/v2/receipt",
|
||||
route: "/dashboard/technical-building-damage/operator",
|
||||
permissions: ["all"],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -85,5 +85,8 @@ export const CREATE_RECEIPT_DAMAGE_ITEMS = api + "/api/v3/damages";
|
||||
export const UPDATE_RECEIPT_DAMAGE_ITEMS = api + "/api/v3/damages";
|
||||
export const ATIVITY_RECEIPT_DAMAGE_ITEMS = api + "/api/v3/damages/activate";
|
||||
|
||||
// damage receipt
|
||||
export const GET_TECHNICAL_DAMAGE_OPERATOR_LIST = api + "/api/v3/receipts";
|
||||
export const GET_DAMAGE_ITEM_LIST = api + "/api/v3/damages/list";
|
||||
// activity code log
|
||||
export const ACTIVITY_LOG = api + "/api/v3/profile/add_activity";
|
||||
|
||||
Reference in New Issue
Block a user