From 3c24f5b115847a687840d870c23c76603798ed0b Mon Sep 17 00:00:00 2001 From: LeonG11 Date: Wed, 24 Jun 2026 12:04:25 +0300 Subject: [PATCH] feat: add page profile with orders --- backend/models/order.go | 2 +- backend/models/user.go | 2 +- frontend/src/App.jsx | 3 +- frontend/src/api/index.js | 5 +- frontend/src/pages/Profile.jsx | 118 +++++++++++++++++++++++++++++++++ 5 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 frontend/src/pages/Profile.jsx diff --git a/backend/models/order.go b/backend/models/order.go index 8aecbd6..4dbde91 100644 --- a/backend/models/order.go +++ b/backend/models/order.go @@ -12,7 +12,7 @@ type Order struct { TotalPrice float64 `json:"total_price" gorm:"not null"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` - Items []OrderItem + Items []OrderItem `json:"items"` } type OrderItem struct { diff --git a/backend/models/user.go b/backend/models/user.go index 4efa857..0ab11f5 100644 --- a/backend/models/user.go +++ b/backend/models/user.go @@ -4,7 +4,7 @@ import "gorm.io/gorm" type User struct { gorm.Model `json:"-"` - Username string `gorm:"unique;not null" binding:"required"` + Username string `json:"username" gorm:"unique;not null" binding:"required"` Password string `gorm:"not null" json:"-" binding:"required,min=8"` Role string `gorm:"default:'customer'" json:"role"` FirstName string `json:"first_name" binding:"required"` diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index aada74e..764e7dc 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -7,6 +7,7 @@ import Shop from "./pages/Shop"; import NotFoundPage from "./pages/NotFoundPage"; import Contact from "./pages/Contact"; import Cart from "./pages/Cart"; +import Profile from "./pages/Profile"; const PrivateRoute = ({ children }) => { const token = localStorage.getItem("token"); @@ -27,6 +28,7 @@ export default function App() { } /> } /> } /> + } /> } /> - } /> diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index ed46b7e..7e06556 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -45,5 +45,8 @@ export const updateCartItem = (id, data) => axios.post(`${API_URL}/cart/${id}`, data); export const removeFromCart = (id) => axios.delete(`${API_URL}/cart/${id}`); export const createOrder = (data) => axios.post(`${API_URL}/orders/`, data); -export const getUserOrders = () => axios.get(`${API_URL}/orders/`); +export const getUserOrders = () => axios.get(`${API_URL}/orders`); export const getOrder = (id) => axios.get(`${API_URL}/orders/${id}`); + +export const updateProfile = () => axios.patch(`${API_URL}/profile`); +export const getUserInfo = () => axios.get(`${API_URL}/profile`); diff --git a/frontend/src/pages/Profile.jsx b/frontend/src/pages/Profile.jsx new file mode 100644 index 0000000..4578dcb --- /dev/null +++ b/frontend/src/pages/Profile.jsx @@ -0,0 +1,118 @@ +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import PageLayout from "../components/PageLayout"; +import { getUserInfo, getUserOrders } from "../api"; + +export default function Profile() { + const [user, setUser] = useState(null); + const [orders, setOrders] = useState([]); + const [loading, setLoading] = useState(true); + const navigate = useNavigate(); + + useEffect(() => { + Promise.all([getUserInfo(), getUserOrders()]) + .then(([userRes, ordersRes]) => { + setUser(userRes.data); + setOrders(ordersRes.data); + }) + .catch(() => { }) + .finally(() => setLoading(false)); + }, []); + + const handleLogout = () => { + localStorage.removeItem("token"); + localStorage.removeItem("user"); + navigate("/"); + }; + + const statusLabels = { + new: "Новый", + packed: "Собирают", + delivered: "Доставлен", + cancel: "Отменен", + }; + + if (loading) { + return ( + +

Загрузка..

+
+ ); + } + return ( + +
+
+

+ Личный кабинет +

+ +
+ +
+

+ {user && ( +
+

+ Имя: {user.first_name || "не указано"}{" "} + {user.last_name || "не указано"} +

+

Телефон: {user.phone || "не указано"}

+

Логин: {user.username}

+
+ )} +

+
+
+

Мои заказы

+ {orders.length === 0 ? ( +

У вас пока нет заказов

+ ) : ( +
+ {orders.map((order) => ( +
+
+ Заказ #{order.id} + + {statusLabels[order.status]} + +
+ +
+ {order.items?.map((oi) => ( +
+ {oi.item?.name} + + {oi.quantity} {oi.item?.unit} x {oi.price}р + +
+ ))} +
+
+ + {order.delivery_address} + + + Итого: {order.total_price} + +
+
+ ))} +
+ )} +
+
+
+ ); +}