._.
This commit is contained in:
parent
5aa92b7ec0
commit
35c7e12bdc
@ -2,7 +2,7 @@ import axios from "axios";
|
|||||||
|
|
||||||
const API_URL = "http://localhost:8000/api";
|
const API_URL = "http://localhost:8000/api";
|
||||||
|
|
||||||
const getAuthToken = () => {
|
export const getAuthToken = () => {
|
||||||
return localStorage.getItem("token");
|
return localStorage.getItem("token");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
13
src/components/Dialog.css
Normal file
13
src/components/Dialog.css
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.modal-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 4);
|
||||||
|
z-index: 1040;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
z-index: 1050;
|
||||||
|
}
|
||||||
71
src/components/SelectionDialog.jsx
Normal file
71
src/components/SelectionDialog.jsx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import './Dialog.css';
|
||||||
|
|
||||||
|
const SelectionDialog = ({ show, handleClose, items, columns, onSelect }) => {
|
||||||
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
const [filteredItems, setFilteredItems] = useState(items);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFilteredItems(
|
||||||
|
items.filter(item =>
|
||||||
|
columns.some(column =>
|
||||||
|
item[column.key].toString().toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [searchTerm, items, columns]);
|
||||||
|
|
||||||
|
if (!show) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="modal-backdrop fade show"></div>
|
||||||
|
<div className="modal show d-block" tabIndex="-1">
|
||||||
|
<div className="modal-dialog">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<h5 className="modal-title">Выбор</h5>
|
||||||
|
<button type="button" className="close" onClick={handleClose}>
|
||||||
|
<span>×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control mb-3"
|
||||||
|
placeholder="Поиск..."
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
<table className="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{columns.map(column => (
|
||||||
|
<th key={column.key}>{column.label}</th>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{filteredItems.map(item => (
|
||||||
|
<tr key={item.id} onClick={() => onSelect(item)}>
|
||||||
|
{columns.map(column => (
|
||||||
|
<td key={column.key}>{item[column.key]}</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="button" className="btn btn-secondary" onClick={handleClose}>
|
||||||
|
Закрыть
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectionDialog;
|
||||||
@ -1,4 +1,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
import SelectionDialog from "../components/SelectionDialog.jsx";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { getAuthToken } from "../api.jsx";
|
||||||
import {
|
import {
|
||||||
getAccessories,
|
getAccessories,
|
||||||
createAccessory,
|
createAccessory,
|
||||||
@ -19,6 +22,8 @@ const Accessories = () => {
|
|||||||
});
|
});
|
||||||
const [editingAccessoryId, setEditingAccessoryId] = useState(null);
|
const [editingAccessoryId, setEditingAccessoryId] = useState(null);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
|
const [showCityDialog, setShowCityDialog] = useState(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchAccessories();
|
fetchAccessories();
|
||||||
@ -83,6 +88,7 @@ const Accessories = () => {
|
|||||||
weight: accessory.weight,
|
weight: accessory.weight,
|
||||||
period: accessory.period,
|
period: accessory.period,
|
||||||
city_id: accessory.city_id,
|
city_id: accessory.city_id,
|
||||||
|
city_name: accessory.city_name,
|
||||||
});
|
});
|
||||||
setEditingAccessoryId(accessory.id);
|
setEditingAccessoryId(accessory.id);
|
||||||
};
|
};
|
||||||
@ -107,6 +113,19 @@ const Accessories = () => {
|
|||||||
setEditingAccessoryId(null);
|
setEditingAccessoryId(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDialogSelectCity = (selectedItem) => {
|
||||||
|
setNewAccessory({
|
||||||
|
...newAccessory,
|
||||||
|
city_id: selectedItem.id,
|
||||||
|
city_name: selectedItem.name,
|
||||||
|
});
|
||||||
|
setShowCityDialog(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (getAuthToken() === null) {
|
||||||
|
navigate("/login");
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mt-4">
|
<div className="container mt-4">
|
||||||
<h3>Аксессуары</h3>
|
<h3>Аксессуары</h3>
|
||||||
@ -159,23 +178,29 @@ const Accessories = () => {
|
|||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
|
||||||
<label htmlFor="citySelect">Город</label>
|
<div className="input-group mb-3">
|
||||||
<select
|
<input
|
||||||
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
id="citySelect"
|
id="cityId"
|
||||||
name="city_id"
|
name="cityId"
|
||||||
value={newAccessory.city_id}
|
placeholder="Выберите город"
|
||||||
onChange={handleInputChange}
|
value={newAccessory.city_name ? newAccessory.city_name : ""}
|
||||||
|
readOnly
|
||||||
|
onClick={() => setShowCityDialog(true)}
|
||||||
|
/>
|
||||||
|
<div className="input-group-append">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-secondary"
|
||||||
|
onClick={() => setShowCityDialog(true)}
|
||||||
>
|
>
|
||||||
<option value="">Выберите город</option>
|
Выбрать
|
||||||
{cities.map((city) => (
|
</button>
|
||||||
<option key={city.id} value={city.id}>
|
|
||||||
{city.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="btn-group">
|
<div className="btn-group">
|
||||||
<button type="submit" className="btn btn-primary">
|
<button type="submit" className="btn btn-primary">
|
||||||
{editingAccessoryId ? "Обновить" : "Создать"}
|
{editingAccessoryId ? "Обновить" : "Создать"}
|
||||||
@ -236,6 +261,17 @@ const Accessories = () => {
|
|||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<SelectionDialog
|
||||||
|
show={showCityDialog}
|
||||||
|
handleClose={() => setShowCityDialog(false)}
|
||||||
|
items={cities}
|
||||||
|
columns={[
|
||||||
|
{ key: "id", label: "ID" },
|
||||||
|
{ key: "name", label: "Название" },
|
||||||
|
]}
|
||||||
|
onSelect={handleDialogSelectCity}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user