feat:
This commit is contained in:
@@ -48,7 +48,7 @@ export const createOrder = (data) => axios.post(`${API_URL}/orders/`, data);
|
||||
export const getUserOrders = () => axios.get(`${API_URL}/orders`);
|
||||
export const getOrder = (id) => axios.get(`${API_URL}/orders/${id}`);
|
||||
|
||||
export const updateProfile = (data) => axios.patch(`${API_URL}/profile`);
|
||||
export const updateProfile = (data) => axios.patch(`${API_URL}/profile`, data);
|
||||
export const getUserInfo = () => axios.get(`${API_URL}/profile`);
|
||||
|
||||
export const uploadItemAvatar = (id, file) => {
|
||||
@@ -58,3 +58,9 @@ export const uploadItemAvatar = (id, file) => {
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
};
|
||||
|
||||
export const getAllOrders = () => axios.get(`${API_URL}/admin/orders`);
|
||||
export const updateOrderStatus = (id, data) =>
|
||||
axios.patch(`${API_URL}/admin/orders/${id}`, data);
|
||||
export const registerAdmin = (data) =>
|
||||
axios.post(`${API_URL}/admin/register`, data);
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { getAllOrders, updateOrderStatus } from "../api/index";
|
||||
|
||||
const STATUSES = [
|
||||
{ value: "new", label: "Новый" },
|
||||
{ value: "packed", label: "Собран" },
|
||||
{ value: "delivered", label: "Доставлен" },
|
||||
{ value: "cancel", label: "Отменён" },
|
||||
];
|
||||
|
||||
export default function AdminOrders() {
|
||||
const [orders, setOrders] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const loadOrders = () => {
|
||||
getAllOrders()
|
||||
.then((res) => setOrders(res.data))
|
||||
.catch(() => { })
|
||||
.finally(() => setLoading(false));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadOrders();
|
||||
}, []);
|
||||
|
||||
const handleStatusChange = async (id, newStatus) => {
|
||||
try {
|
||||
await updateOrderStatus(id, { status: newStatus });
|
||||
setOrders((prev) =>
|
||||
prev.map((o) => (o.id === id ? { ...o, status: newStatus } : o)),
|
||||
);
|
||||
} catch {
|
||||
alert("Не удалось изменить статус");
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) return <p className="text-white/60">Загрузка...</p>;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{orders.length === 0 ? (
|
||||
<p className="text-white/60">Заказов нет</p>
|
||||
) : (
|
||||
orders.map((order) => (
|
||||
<div
|
||||
key={order.id}
|
||||
className="bg-white/5 rounded-lg p-4 border border-white/10"
|
||||
>
|
||||
{/* шапка: номер + селект статуса */}
|
||||
<div className="flex justify-between items-center mb-3">
|
||||
<span className="font-medium text-white">Заказ #{order.id}</span>
|
||||
<select
|
||||
value={order.status}
|
||||
onChange={(e) => handleStatusChange(order.id, e.target.value)}
|
||||
className="bg-slate-700 text-white text-sm rounded px-3 py-1 border border-white/10"
|
||||
>
|
||||
{STATUSES.map((s) => (
|
||||
<option key={s.value} value={s.value}>
|
||||
{s.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* товары заказа */}
|
||||
<div className="flex flex-col gap-2 mb-3 text-sm text-white/70">
|
||||
{order.items?.map((oi) => (
|
||||
<div key={oi.id} className="flex items-center gap-3">
|
||||
<img
|
||||
src={`/static/items/${oi.item?.avatar_url}`}
|
||||
alt=""
|
||||
className="w-20 h-20 object-cover rounded shrink-0"
|
||||
/>
|
||||
<span className="grow">{oi.item?.name}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{oi.quantity} {oi.item?.unit} × {oi.price} ₽
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* подвал: адрес + итог */}
|
||||
<div className="flex justify-between pt-2 border-t border-white/10 text-sm">
|
||||
<span className="text-white/50">{order.delivery_address}</span>
|
||||
<span className="font-medium text-white">
|
||||
Итого: {order.total_price} ₽
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import PageLayout from "../components/PageLayout";
|
||||
import AdminItems from "../components/AdminItems";
|
||||
// import AdminOrders from "../components/AdminOrders"; // добавим позже
|
||||
import AdminOrders from "../components/AdminOrders"; // добавим позже
|
||||
// import AdminStaff from "../components/AdminStaff"; // добавим позже
|
||||
|
||||
export default function AdminPage() {
|
||||
@@ -38,9 +38,7 @@ export default function AdminPage() {
|
||||
|
||||
{/* Содержимое активной вкладки */}
|
||||
{tab === "items" && <AdminItems />}
|
||||
{tab === "orders" && (
|
||||
<p className="text-white/50">Раздел заказов — в разработке</p>
|
||||
)}
|
||||
{tab === "orders" && <AdminOrders />}
|
||||
{tab === "staff" && (
|
||||
<p className="text-white/50">Раздел сотрудников — в разработке</p>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user