Untitled
unknown
plain_text
6 months ago
18 kB
3
Indexable
import React, { useEffect } from "react"; import { Stack, TextField, Autocomplete, Button, Typography, Grid, Divider, InputAdornment, Box, } from "@mui/material"; import { useFormik } from "formik"; import * as yup from "yup"; import { getCurrentUser, useUser } from "src/common/api"; import { CompanyType, User } from "src/common/types"; import { CeButton, CeMuiPhoneNumber, CeTextField } from "src/common/components"; import { Add01Icon, Delete01Icon, Tick02Icon } from "@hugeicons/react"; import countries from "src/common/utils/countries"; import { useTranslation } from "react-i18next"; import { useCompany, useUpdateCompany } from "src/common/api/company"; import { useRecoilState } from "recoil"; import { companyFormValuesState } from "src/common/state/company"; import { turnCompanyFormValuesIntoUpdateDto, turnCompanyIntoFormValues, } from "src/common/utils/company"; interface SettingsCompanyProfileProps { userId?: number; } export const SettingsCompanyProfile: React.FC<SettingsCompanyProfileProps> = ({ userId, }) => { const { t } = useTranslation(["common", "manager", "dispatcher"]); const [companyFormValues, setCompanyFormValues] = useRecoilState( companyFormValuesState ); const { data: user, isLoading: isFullUserLoading, isSuccess: isFullUserSuccess, refetch: refetchUser, } = useUser(userId, Boolean(userId)); const { mutate: handleUpdateCompany, isSuccess: isUpdateCompanySuccess, isLoading: isUpdateCompanyLoading, } = useUpdateCompany(); const isLoading = isFullUserLoading || isUpdateCompanyLoading; const formik = useFormik({ initialValues: companyFormValues, enableReinitialize: true, validationSchema: yup.object({ name: yup.string().required("Name is required"), type: yup.string().required("Type is required"), contactEmail: yup.string().email("Invalid email").nullable(), billingEmail: yup.string().email("Invalid email").nullable(), planningEmail: yup.string().email("Invalid email").nullable(), phoneNumber: yup.string().required("Phone number is required"), address: yup.string().required("Address is required"), secondaryAddress: yup.string().nullable(), vatNumber: yup.string().required("Vat number is required"), zipCode: yup.string().required("zip code is required").nullable(), city: yup.string().required("City is required"), country: yup.object().required("Country is required").nullable(), }), onSubmit: async (values) => { if (user?.company?.id) { const payload = turnCompanyFormValuesIntoUpdateDto({ ...values, companyId: user.companyId, }); handleUpdateCompany(payload); } }, }); useEffect(() => { if (user?.companyId && isFullUserSuccess) { const companyFormValues = turnCompanyIntoFormValues(user.company); setCompanyFormValues(companyFormValues); } }, [user?.company, isFullUserSuccess]); const handleAddTaxBracket = () => { formik.setFieldValue("taxes", [ ...formik.values.taxes, { name: "", percentage: null }, ]); }; const handleRemoveTaxBracket = (index: number) => { const updatedTaxes = formik.values.taxes.filter((_, i) => i !== index); formik.setFieldValue("taxes", updatedTaxes); }; return ( <form onSubmit={formik.handleSubmit}> {/* General*/} <Box sx={{ paddingY: 2, paddingX: 1.5 }}> <Box> <Typography variant="body1" color="text.disabled" fontWeight="bold" gutterBottom > {t("General")} </Typography> <Divider sx={{ marginBottom: 2, marginTop: 2 }} /> </Box> <Box display="flex" flexDirection="column" gap={3} sx={{ paddingY: 1.5, paddingX: 3, width: "90%" }}> {/* Company Name & Type */} <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("company-name-type")} </Typography> <Box display="flex" flex="70%" gap={2}> <Box flex="1"> <CeTextField fullWidth id="name" name="name" size="small" placeholder={t("name")} value={formik.values.name} onChange={formik.handleChange} error={formik.touched.name && Boolean(formik.errors.name)} helperText={formik.touched.name && formik.errors.name} disabled={isLoading} required /> </Box> <Box flex="1"> <Autocomplete id="type" fullWidth value={formik.values.type || null} onChange={(event: any, newValue: string | null) => { formik.setFieldValue("type", newValue || null); }} options={Object.values(CompanyType)} getOptionLabel={(option) => option} renderInput={(params) => ( <CeTextField {...params} size="small" placeholder={t("dispatcher:type")} InputLabelProps={{ shrink: true }} error={ formik.touched.type && Boolean(formik.errors.type) } helperText={formik.touched.type && formik.errors.type} required /> )} /> </Box> </Box> </Box> {/* Company VAT Number */} <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("company-vat-number")} </Typography> <Box display="flex" flex="70%" gap={2}> <CeTextField fullWidth id="vatNumber" name="vatNumber" size="small" placeholder={t("vat-number")} value={formik.values.vatNumber} onChange={formik.handleChange} disabled={isLoading} error={ formik.touched.vatNumber && Boolean(formik.errors.vatNumber) } helperText={formik.touched.vatNumber && formik.errors.vatNumber} required /> </Box> </Box> {/* Company Address */} <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("company-address")} </Typography> <Box display="flex" flex="70%" gap={2}> <Box flex="1"> <CeTextField fullWidth id="address" name="address" size="small" placeholder={t("address-line")} value={formik.values.address} onChange={formik.handleChange} disabled={isLoading} error={ formik.touched.address && Boolean(formik.errors.address) } helperText={formik.touched.address && formik.errors.address} required /> </Box> <Box flex="1"> <CeTextField fullWidth id="secondaryAddress" name="secondaryAddress" size="small" placeholder={t("additional-address-line")} value={formik.values.secondaryAddress} onChange={formik.handleChange} disabled={isLoading} /> </Box> </Box> </Box> {/* Region */} <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("region")} </Typography> <Box display="flex" flex="70%" gap={2}> <Box flex="1"> <CeTextField fullWidth id="zipCode" name="zipCode" size="small" placeholder={t("zip-code")} value={formik.values.zipCode} onChange={formik.handleChange} disabled={isLoading} error={ formik.touched.zipCode && Boolean(formik.errors.zipCode) } helperText={formik.touched.zipCode && formik.errors.zipCode} required /> </Box> <Box flex="1"> <CeTextField fullWidth id="city" name="city" size="small" placeholder={t("dispatcher:city")} value={formik.values.city} onChange={formik.handleChange} disabled={isLoading} error={formik.touched.city && Boolean(formik.errors.city)} helperText={formik.touched.city && formik.errors.city} required /> </Box> <Box flex="1"> <Autocomplete fullWidth id="country" size="small" value={formik.values.country || null} onChange={(_, selectedCountry) => { formik.setFieldValue("country", selectedCountry); }} options={countries} getOptionLabel={(option) => option?.label || ""} isOptionEqualToValue={(option, value) => option.value === value?.value } renderInput={(params) => ( <CeTextField {...params} InputLabelProps={{ shrink: true }} error={ formik.touched.country && Boolean(formik.errors.country) } helperText={ formik.touched.country && formik.errors.country } disabled={isLoading} placeholder={t("country")} size="small" required /> )} /> </Box> </Box> </Box> {/* Company Phone Number */} <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("company-phone-number")} </Typography> <Box display="flex" flex="70%"> <CeMuiPhoneNumber fullWidth defaultCountry={"be"} id="phoneNumber" name="phoneNumber" size="small" placeholder={t("phone-number")} value={formik.values.phoneNumber} onChange={(value) => formik.setFieldValue("phoneNumber", value)} onBlur={() => formik.setFieldTouched("phoneNumber", true)} error={ formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber) } helperText={ formik.touched.phoneNumber && formik.errors.phoneNumber } disabled={isLoading} variant="outlined" required /> </Box> </Box> {/* Company Emails */} <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("company-email-contact")} </Typography> <Box display="flex" flex="70%"> <CeTextField fullWidth id="contactEmail" name="contactEmail" size="small" placeholder={t("contact-address")} value={formik.values.contactEmail} onChange={formik.handleChange} disabled={isLoading} /> </Box> </Box> <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("company-email-billing")} </Typography> <Box display="flex" flex="70%"> <CeTextField fullWidth id="billingEmail" name="billingEmail" size="small" placeholder={t("billing-address")} value={formik.values.billingEmail} onChange={formik.handleChange} disabled={isLoading} /> </Box> </Box> <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("company-email-planning")} </Typography> <Box display="flex" flex="70%"> <CeTextField fullWidth id="planningEmail" name="planningEmail" size="small" placeholder={t("planning-address")} value={formik.values.planningEmail} onChange={formik.handleChange} disabled={isLoading} /> </Box> </Box> </Box> </Box> {/* Taxes Header */} <Box sx={{ paddingY: 2, paddingX: 1.5 }}> <Box> <Typography variant="body1" color="text.disabled" fontWeight="bold" gutterBottom > {t("Taxes")} </Typography> <Divider sx={{ marginBottom: 2, marginTop: 2 }} /> </Box> {formik.values.taxes.map((tax, index) => { const taxErrors = formik.errors.taxes?.[index]; return ( <Box display="flex" flexDirection="column" gap={2} sx={{ paddingY: 1.5, paddingX: 3, width: "90%" }}> <Box display="flex" alignItems="center" gap={2}> <Typography variant="body2" sx={{flex:"30%"}}> {t("taxes")} </Typography> <Box display="flex" alignItems="center" flex="70%" gap={2}> {/* Tax Name Field */} <Box flex="1"> <CeTextField id={`taxes[${index}].name`} name={`taxes[${index}].name`} placeholder={t("tax-name")} fullWidth size="small" value={tax.name} onChange={formik.handleChange} InputLabelProps={{ shrink: true }} error={ !!( formik.touched.taxes?.[index]?.name && taxErrors && typeof taxErrors === "object" && taxErrors?.name ) } helperText={ formik.touched.taxes?.[index]?.name && taxErrors && typeof taxErrors === "object" && taxErrors?.name } /> </Box> {/* Tax Percentage Field */} <Box flex="1"> <CeTextField fullWidth id={`taxes[${index}].percentage`} name={`taxes[${index}].percentage`} placeholder={t("percentage")} size="small" type="number" value={tax.percentage ?? ""} onChange={formik.handleChange} InputProps={{ endAdornment: ( <InputAdornment position="end">%</InputAdornment> ), }} error={ !!( formik.touched.taxes?.[index]?.percentage && taxErrors && typeof taxErrors === "object" && taxErrors?.percentage ) } helperText={ formik.touched.taxes?.[index]?.percentage && taxErrors && typeof taxErrors === "object" && taxErrors?.percentage } /> </Box> {/* Remove Button */} <Box flex="0.1" alignItems="center"> {formik.values.taxes.length > 1 && ( <CeButton type="button" onClick={() => handleRemoveTaxBracket(index)} color="error" variant="text" size="small" > <Delete01Icon /> </CeButton> )} </Box> </Box> </Box> </Box> ); })} {/* Add New Tax Button */} <Box display="flex" alignItems="center" gap={2} sx={{ paddingY: 1.5, paddingX: 3, width: "90%" }}> <Box sx={{flex:"30%"}}> </Box> <Box display="flex" flex="70%"> <CeButton type="button" onClick={handleAddTaxBracket} variant="outlined" size="large" > {t("add-tax-bracket")} </CeButton> </Box> </Box> </Box> {/* Submit Button */} <Box sx={{ padding: "16px 24px" }}> <Grid item xs={12} sx={{ display: "flex", justifyContent: "flex-end", marginTop: 3 }} > <CeButton variant="text" onClick={() => formik.resetForm()} disabled={isLoading} sx={{ marginRight: 1 }} > {t("cancel")} </CeButton> <CeButton type="submit" variant="contained" disabled={isLoading} endIcon={ <Tick02Icon size={20} color={"currentColor"} variant={"stroke"} /> } > {t("manager:save")} </CeButton> </Grid> </Box> </form> ); };
Editor is loading...
Leave a Comment