Initial commit
This commit is contained in:
282
src/components/branches/CreateBranches.jsx
Normal file
282
src/components/branches/CreateBranches.jsx
Normal file
@@ -0,0 +1,282 @@
|
||||
'use client';
|
||||
|
||||
import { Map, Placemark, YMaps } from '@pbe/react-yandex-maps';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useEffect, useState } from 'react';
|
||||
import axiosInstance from '../../api/axiosInstance';
|
||||
|
||||
// Reverse geocoding (OSM orqali)
|
||||
async function getAddress(lat, lon) {
|
||||
const response = await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json`);
|
||||
const data = await response.json();
|
||||
const address = data.address || {};
|
||||
|
||||
return {
|
||||
fullAddress: data.display_name || '',
|
||||
country: address.country || '',
|
||||
region: address.state || '',
|
||||
city: address.city || address.town || address.village || '',
|
||||
street: address.road || '',
|
||||
house: address.house_number || '',
|
||||
postalCode: address.postcode || '',
|
||||
};
|
||||
}
|
||||
|
||||
const CreateBranches = ({ branches, setAlert, setBranches }) => {
|
||||
const queryClient = useQueryClient();
|
||||
const [formData, setFormData] = useState({
|
||||
id: '',
|
||||
title: '',
|
||||
titleRu: '',
|
||||
address: '',
|
||||
addressRu: '',
|
||||
workingHours: '',
|
||||
workingHoursRu: '',
|
||||
phone: '',
|
||||
telegramAdmin: '',
|
||||
telegramChannel: '',
|
||||
code: '',
|
||||
active: true,
|
||||
});
|
||||
|
||||
const [coords, setCoords] = useState({
|
||||
latitude: 41.311081, // Toshkent
|
||||
longitude: 69.240562,
|
||||
});
|
||||
|
||||
const [locationDetails, setLocationDetails] = useState({
|
||||
fullAddress: '',
|
||||
country: '',
|
||||
region: '',
|
||||
city: '',
|
||||
street: '',
|
||||
house: '',
|
||||
postalCode: '',
|
||||
});
|
||||
|
||||
const resetForm = () => {
|
||||
setFormData({
|
||||
id: '',
|
||||
title: '',
|
||||
titleRu: '',
|
||||
address: '',
|
||||
addressRu: '',
|
||||
workingHours: '',
|
||||
workingHoursRu: '',
|
||||
phone: '',
|
||||
telegramAdmin: '',
|
||||
telegramChannel: '',
|
||||
code: '',
|
||||
active: true,
|
||||
});
|
||||
setCoords({
|
||||
latitude: 41.311081,
|
||||
longitude: 69.240562,
|
||||
});
|
||||
setLocationDetails({
|
||||
fullAddress: '',
|
||||
country: '',
|
||||
region: '',
|
||||
city: '',
|
||||
street: '',
|
||||
house: '',
|
||||
postalCode: '',
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (locationDetails.fullAddress) {
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
address: locationDetails.fullAddress,
|
||||
addressRu: locationDetails.fullAddress,
|
||||
}));
|
||||
}
|
||||
}, [locationDetails]);
|
||||
|
||||
const { data: branchData, refetch } = useQuery({
|
||||
queryKey: ['one_branch', branches],
|
||||
queryFn: () => axiosInstance.get(`/branches/${branches}`).then((res) => res.data),
|
||||
enabled: !!branches,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (branches) {
|
||||
refetch();
|
||||
}
|
||||
}, [branches, refetch]);
|
||||
|
||||
useEffect(() => {
|
||||
if (branchData) {
|
||||
setFormData({
|
||||
id: branchData.id || '',
|
||||
title: branchData.title || '',
|
||||
titleRu: branchData.titleRu || '',
|
||||
address: branchData.address || '',
|
||||
addressRu: branchData.addressRu || '',
|
||||
workingHours: branchData.workingHours || '',
|
||||
workingHoursRu: branchData.workingHoursRu || '',
|
||||
phone: branchData.phone || '',
|
||||
telegramAdmin: branchData.telegramAdmin || '',
|
||||
telegramChannel: branchData.telegramChannel || '',
|
||||
code: branchData.code || '',
|
||||
active: branchData.active ?? true,
|
||||
});
|
||||
setCoords({
|
||||
latitude: branchData.latitude || 41.311081,
|
||||
longitude: branchData.longitude || 69.240562,
|
||||
});
|
||||
}
|
||||
}, [branchData]);
|
||||
|
||||
const { mutate: createBranch } = useMutation({
|
||||
mutationFn: (body) => axiosInstance.post('/branches', body),
|
||||
onSuccess: () => {
|
||||
setAlert({ type: 'success', message: "Filial muvaffaqiyatli qo'shildi." });
|
||||
queryClient.invalidateQueries({ queryKey: ['branch_list'] });
|
||||
resetForm();
|
||||
},
|
||||
onError: () => {
|
||||
setAlert({
|
||||
type: 'warning',
|
||||
message: "Filial qo'shilmadi, xatolik yuz berdi.",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const { mutate: editBranch } = useMutation({
|
||||
mutationFn: (body) => axiosInstance.put(`/branches/${body.id}`, body),
|
||||
onSuccess: () => {
|
||||
setBranches(null);
|
||||
setAlert({
|
||||
type: 'success',
|
||||
message: 'Filial muvaffaqiyatli yangilandi.',
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ['branch_list'] });
|
||||
resetForm();
|
||||
},
|
||||
onError: () => {
|
||||
setAlert({
|
||||
type: 'warning',
|
||||
message: 'Filial yangilanmadi, xatolik yuz berdi.',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const addBranch = () => {
|
||||
const { id, ...dataWithoutId } = formData;
|
||||
createBranch({
|
||||
...dataWithoutId,
|
||||
latitude: Number(coords.latitude) || 0,
|
||||
longitude: Number(coords.longitude) || 0,
|
||||
});
|
||||
};
|
||||
|
||||
const updateBranch = (id) => {
|
||||
editBranch({
|
||||
...formData,
|
||||
id,
|
||||
latitude: Number(coords.latitude) || 0,
|
||||
longitude: Number(coords.longitude) || 0,
|
||||
});
|
||||
};
|
||||
|
||||
const handleMapClick = async (e) => {
|
||||
const lat = e.get('coords')[0];
|
||||
const lon = e.get('coords')[1];
|
||||
setCoords({ latitude: lat, longitude: lon });
|
||||
const details = await getAddress(lat, lon);
|
||||
setLocationDetails(details);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col bg-white shadow rounded-lg p-6 mb-6">
|
||||
<div className="h-96 mb-10">
|
||||
<YMaps query={{ lang: 'en_RU' }}>
|
||||
<Map
|
||||
defaultState={{
|
||||
center: [coords.latitude, coords.longitude],
|
||||
zoom: 13,
|
||||
}}
|
||||
width="100%"
|
||||
height="400px"
|
||||
onClick={handleMapClick}
|
||||
>
|
||||
<Placemark geometry={[coords.latitude, coords.longitude]} />
|
||||
</Map>
|
||||
</YMaps>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{Object.keys(formData)
|
||||
.filter((key) => key !== 'id')
|
||||
.map((key) => (
|
||||
<div key={key} className="flex flex-col">
|
||||
<label className="mb-1 font-semibold text-slate-700">
|
||||
{key === 'title'
|
||||
? 'Filial nomi'
|
||||
: key === 'titleRu'
|
||||
? 'Filial nomi (RU)'
|
||||
: key === 'address'
|
||||
? 'Manzil'
|
||||
: key === 'addressRu'
|
||||
? 'Manzil (RU)'
|
||||
: key === 'workingHours'
|
||||
? 'Ish vaqti'
|
||||
: key === 'workingHoursRu'
|
||||
? 'Ish vaqti (RU)'
|
||||
: key === 'phone'
|
||||
? 'Telefon'
|
||||
: key === 'telegramAdmin'
|
||||
? 'Telegram Admin'
|
||||
: key === 'telegramChannel'
|
||||
? 'Telegram Kanal'
|
||||
: key === 'code'
|
||||
? 'Kod'
|
||||
: key === 'active'
|
||||
? 'Faol'
|
||||
: key}
|
||||
</label>
|
||||
{key === 'active' ? (
|
||||
<div className="flex items-center gap-3">
|
||||
<button type="button" onClick={() => setFormData({ ...formData, active: !formData.active })} className={`w-14 h-8 flex items-center rounded-full p-1 transition-colors duration-300 ${formData.active ? 'bg-[#3489e3]' : 'bg-gray-300'}`}>
|
||||
<div className={`w-6 h-6 bg-white rounded-full shadow-md transform transition-transform duration-300 ${formData.active ? 'translate-x-6' : 'translate-x-0'}`}></div>
|
||||
</button>
|
||||
<span>{formData.active ? 'Faol' : 'Faol emas'}</span>
|
||||
</div>
|
||||
) : (
|
||||
<input
|
||||
type="text"
|
||||
className="border border-slate-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-[#3489e3]"
|
||||
value={formData[key]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
[key]: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-3 mb-8 mt-6">
|
||||
{!branches && (
|
||||
<button onClick={addBranch} className="bg-[#3489e3] hover:bg-blue-500 text-white px-5 py-2 rounded-lg shadow">
|
||||
Yaratish
|
||||
</button>
|
||||
)}
|
||||
{branches && (
|
||||
<button onClick={() => updateBranch(formData.id)} disabled={!formData.id} className={`px-5 py-2 rounded-lg shadow text-white ${!formData.id ? 'bg-gray-400 cursor-not-allowed' : 'bg-[#3489e3] hover:bg-blue-500'}`}>
|
||||
Yangilash
|
||||
</button>
|
||||
)}
|
||||
<button onClick={resetForm} className="bg-gray-400 hover:bg-gray-500 text-white px-5 py-2 rounded-lg shadow">
|
||||
Tozalash
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateBranches;
|
||||
Reference in New Issue
Block a user