366 lines
10 KiB
JavaScript
366 lines
10 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import {
|
|
TextField,
|
|
Button,
|
|
Card,
|
|
Grid,
|
|
Typography,
|
|
FormHelperText,
|
|
Autocomplete,
|
|
CircularProgress,
|
|
} from "@mui/material";
|
|
import { useNavigate } from "react-router-dom";
|
|
import toast from "react-hot-toast";
|
|
import axios from "axios";
|
|
import { isAutheticated } from "src/auth";
|
|
import { City, State } from "country-state-city";
|
|
|
|
const AddPrincipalDistributor = () => {
|
|
const navigate = useNavigate();
|
|
const token = isAutheticated();
|
|
|
|
const [user, setUser] = useState({
|
|
name: "",
|
|
email: "",
|
|
phone: "",
|
|
});
|
|
|
|
const [data, setData] = useState({
|
|
street: "",
|
|
city: "",
|
|
state: "",
|
|
postalCode: "",
|
|
country: "India",
|
|
tradeName: "",
|
|
gstNumber: "",
|
|
panNumber: "",
|
|
});
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
const [stateOptions, setStateOptions] = useState([]);
|
|
const [cityOptions, setCityOptions] = useState([]);
|
|
const [selectedState, setSelectedState] = useState(null);
|
|
const [selectedCity, setSelectedCity] = useState(null);
|
|
|
|
useEffect(() => {
|
|
const fetchStates = async () => {
|
|
const states = State.getStatesOfCountry("IN").map((state) => ({
|
|
label: state.name,
|
|
value: state.isoCode,
|
|
}));
|
|
setStateOptions(states);
|
|
};
|
|
fetchStates();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const fetchCities = async () => {
|
|
if (selectedState) {
|
|
const cities = City.getCitiesOfState("IN", selectedState.value).map(
|
|
(city) => ({
|
|
label: city.name,
|
|
value: city.name,
|
|
})
|
|
);
|
|
setCityOptions(cities);
|
|
}
|
|
};
|
|
fetchCities();
|
|
}, [selectedState]);
|
|
|
|
const handleInputChange = (e) => {
|
|
setUser({ ...user, [e.target.name]: e.target.value });
|
|
};
|
|
|
|
const handleDataChange = (e) => {
|
|
setData({ ...data, [e.target.name]: e.target.value });
|
|
};
|
|
|
|
const handleStateChange = (event, newValue) => {
|
|
setSelectedState(newValue);
|
|
};
|
|
|
|
const handleCityChange = (event, newValue) => {
|
|
setSelectedCity(newValue);
|
|
};
|
|
|
|
const generatePassword = (name, email) => {
|
|
const combinedStr = (name + email).toLowerCase();
|
|
const specialChars = "@#*";
|
|
const alphaChars = combinedStr.match(/[a-zA-Z]/g);
|
|
const filteredChars = combinedStr.match(/[^\W_]/g);
|
|
let passwordChars = alphaChars.concat(filteredChars);
|
|
|
|
const specialChar = specialChars.charAt(
|
|
Math.floor(Math.random() * specialChars.length)
|
|
);
|
|
const randomIndex = Math.floor(Math.random() * (passwordChars.length + 1));
|
|
passwordChars.splice(randomIndex, 0, specialChar);
|
|
|
|
passwordChars = passwordChars.sort(() => Math.random() - 0.5);
|
|
const password = passwordChars.join("").slice(0, 8);
|
|
return password;
|
|
};
|
|
|
|
const handleFormSubmit = async (e) => {
|
|
e.preventDefault();
|
|
try {
|
|
if (
|
|
!user.name ||
|
|
!user.email ||
|
|
!user.phone ||
|
|
!selectedState ||
|
|
!selectedCity ||
|
|
!data.street ||
|
|
!data.postalCode
|
|
) {
|
|
throw new Error("Fill all fields!");
|
|
}
|
|
setLoading(true);
|
|
const generatedPassword = generatePassword(user.name, user.email);
|
|
|
|
const userResponse = await axios.post("/api/v1/user/register", {
|
|
...user,
|
|
password: generatedPassword,
|
|
});
|
|
|
|
if (userResponse.status === 201) {
|
|
const userId = userResponse.data.userId;
|
|
|
|
const addressResponse = await axios.post(
|
|
`/api/shipping/address/admin/new/${userId}`,
|
|
{
|
|
...data,
|
|
state: selectedState.label, // Send selected state label
|
|
city: selectedCity.label, // Send selected city label
|
|
},
|
|
{
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
}
|
|
);
|
|
setLoading(false);
|
|
if (addressResponse.status === 201) {
|
|
toast.success("Principal Distributor and Address Added Successfully");
|
|
navigate("/principal-distributor");
|
|
}
|
|
}
|
|
} catch (error) {
|
|
setLoading(false);
|
|
console.error("Error adding principal distributor and address:", error);
|
|
toast.error(error.response?.data?.message || "Something went wrong!");
|
|
}
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
navigate("/principal-distributor");
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<Card
|
|
sx={{ padding: "1rem", marginBottom: "1rem", position: "relative" }}
|
|
>
|
|
<Button
|
|
variant="outlined"
|
|
color="secondary"
|
|
onClick={handleCancel}
|
|
sx={{ position: "absolute", top: "10px", right: "10px" }}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Typography variant="h5" sx={{ mb: 3 }}>
|
|
Add Principal Distributor
|
|
</Typography>
|
|
<form onSubmit={handleFormSubmit}>
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
Basic Information
|
|
</Typography>
|
|
<Grid container spacing={2} sx={{ mb: 2 }}>
|
|
<Grid item xs={12} sm={4}>
|
|
<TextField
|
|
id="name"
|
|
required
|
|
type="text"
|
|
fullWidth
|
|
name="name"
|
|
value={user.name}
|
|
label="Name"
|
|
variant="outlined"
|
|
onChange={handleInputChange}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} sm={4}>
|
|
<TextField
|
|
id="email"
|
|
required
|
|
type="email"
|
|
fullWidth
|
|
name="email"
|
|
value={user.email}
|
|
label="Email"
|
|
variant="outlined"
|
|
onChange={handleInputChange}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} sm={4}>
|
|
<TextField
|
|
id="phone"
|
|
required
|
|
type="text"
|
|
fullWidth
|
|
name="phone"
|
|
value={user.phone}
|
|
label="Phone Number"
|
|
variant="outlined"
|
|
onChange={handleInputChange}
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
Business Details
|
|
</Typography>
|
|
<Grid container spacing={2} sx={{ mb: 2 }}>
|
|
<Grid item xs={12} sm={4}>
|
|
<TextField
|
|
id="panNumber"
|
|
required
|
|
type="text"
|
|
fullWidth
|
|
name="panNumber"
|
|
value={data.panNumber}
|
|
label="PAN Number"
|
|
variant="outlined"
|
|
onChange={handleDataChange}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} sm={4}>
|
|
<TextField
|
|
id="tradeName"
|
|
// required
|
|
type="text"
|
|
fullWidth
|
|
name="tradeName"
|
|
value={data.tradeName}
|
|
label="Trade Name"
|
|
variant="outlined"
|
|
onChange={handleDataChange}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} sm={4}>
|
|
<TextField
|
|
id="gstNumber"
|
|
// required
|
|
type="text"
|
|
fullWidth
|
|
name="gstNumber"
|
|
value={data.gstNumber}
|
|
label="GST Number"
|
|
variant="outlined"
|
|
onChange={handleDataChange}
|
|
/>
|
|
</Grid>
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
Address
|
|
</Typography>
|
|
<Grid item xs={12} sm={4}>
|
|
<TextField
|
|
id="country"
|
|
required
|
|
type="text"
|
|
fullWidth
|
|
name="country"
|
|
value={data.country}
|
|
label="Country"
|
|
variant="outlined"
|
|
disabled
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} sm={4}>
|
|
<Autocomplete
|
|
id="state"
|
|
options={stateOptions}
|
|
getOptionLabel={(option) => option.label}
|
|
value={selectedState}
|
|
onChange={handleStateChange}
|
|
renderInput={(params) => (
|
|
<TextField
|
|
{...params}
|
|
fullWidth
|
|
label="State"
|
|
variant="outlined"
|
|
error={!selectedState}
|
|
helperText={!selectedState ? "Select a state" : null}
|
|
/>
|
|
)}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} sm={4}>
|
|
<Autocomplete
|
|
id="city"
|
|
options={cityOptions}
|
|
getOptionLabel={(option) => option.label}
|
|
value={selectedCity}
|
|
onChange={handleCityChange}
|
|
renderInput={(params) => (
|
|
<TextField
|
|
{...params}
|
|
fullWidth
|
|
label="City"
|
|
variant="outlined"
|
|
error={!selectedCity}
|
|
helperText={!selectedCity ? "Select a city" : null}
|
|
/>
|
|
)}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
id="street"
|
|
required
|
|
type="text"
|
|
fullWidth
|
|
name="street"
|
|
value={data.street}
|
|
label="Street"
|
|
variant="outlined"
|
|
onChange={handleDataChange}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
id="postalCode"
|
|
required
|
|
type="text"
|
|
fullWidth
|
|
name="postalCode"
|
|
value={data.postalCode}
|
|
label="Postal Code"
|
|
variant="outlined"
|
|
onChange={handleDataChange}
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<Button
|
|
type="submit"
|
|
disabled={loading}
|
|
variant="contained"
|
|
color="primary"
|
|
>
|
|
{loading ? (
|
|
<CircularProgress size={24} />
|
|
) : (
|
|
"Create Principal Distributor"
|
|
)}
|
|
</Button>
|
|
</form>
|
|
</Card>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AddPrincipalDistributor;
|