Untitled
unknown
plain_text
a year ago
18 kB
12
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