diff --git a/app/ProfilePage/page.jsx b/app/ProfilePage/page.jsx new file mode 100644 index 0000000..613d788 --- /dev/null +++ b/app/ProfilePage/page.jsx @@ -0,0 +1,109 @@ +"use client"; + +import React from "react"; +import { useRouter } from "next/navigation"; +import { FaUserCircle, FaStar } from "react-icons/fa"; +import TabBar from "../components/TabBar"; + +const ProfilePage = () => { + const router = useRouter(); + + const fullName = "Иванов Александр Сергеевич"; + const birthDate = "12.03.1990"; + const rating = 4.8; + + return ( +
+
+ {/* Header с кнопкой назад и заголовком по центру */} +
+ +

+ Профиль +

+ +
+ + {/* Карточка профиля */} +
+ {/* Аватар */} + + + {/* ФИО и рейтинг */} +
+ {/*

+ ФИО +

*/} +

+ {fullName} +

+ + {/* Рейтинг + звезды */} +
+ + Рейтинг: {rating.toFixed(1)} + +
+ {[1, 2, 3, 4, 5].map((star) => ( + + ))} +
+
+
+ + {/* Контакты и день рождения */} +
+

+ Дата рождения: {birthDate} +

+

+ Почта: example@mail.com +

+

+ Телефон: +7 (900) 000-00-00 +

+
+ + {/* Кнопки */} +
+ + +
+
+ + +
+
+ ); +}; + +export default ProfilePage; diff --git a/app/components/RequestDetailsModal.jsx b/app/components/RequestDetailsModal.jsx index 1aa4d5a..f9e25a6 100644 --- a/app/components/RequestDetailsModal.jsx +++ b/app/components/RequestDetailsModal.jsx @@ -43,7 +43,7 @@ const RequestDetailsModal = ({ request, onClose }) => { {/* Белая карточка как на макете */}
-
+
{/* Статус + срок (берём цвет и текст из заявки) */}
{ {isRejected && ( <> {request.rejectReason && ( -
+

Причина отказа

@@ -147,7 +147,7 @@ const RequestDetailsModal = ({ request, onClose }) => { + + {/* Заголовок */} +

+ Задача +

+

+ {request.title} +

+ + {/* Сумма и время */} +
+
+ + Сумма + + + {request.amount || "2000 ₽"} + +
+
+ + Выполнить до + + + {request.deadline || "17:00"} + +
+
+ + {/* Список покупок / описание */} +
+

+ {request.description || + "Необходимо приобрести:\n1. Белый хлеб\n2. Молоко\n3. Колбаса\n4. Фрукты"} +

+
+ + {/* Данные человека */} +
+

+ Данные: +

+

+ ФИО: {request.fullName || "Клавдия Березова"} +

+

+ Место: {request.address} +

+ {request.flat && ( +

+ кв: {request.flat} +

+ )} + {request.floor && ( +

+ Этаж: {request.floor} +

+ )} +
+ + {/* Кнопка отклика внизу */} + +
+
+ ); +}; + +export default AcceptPopup; diff --git a/app/historyRequest/page.jsx b/app/historyRequest/page.jsx index ddfe293..1694663 100644 --- a/app/historyRequest/page.jsx +++ b/app/historyRequest/page.jsx @@ -99,7 +99,7 @@ const HistoryRequestPage = () => {
-

+

Александр

@@ -111,7 +111,7 @@ const HistoryRequestPage = () => { -

+

История заявок

diff --git a/app/mainValounter/page.jsx b/app/mainValounter/page.jsx new file mode 100644 index 0000000..9714e3d --- /dev/null +++ b/app/mainValounter/page.jsx @@ -0,0 +1,202 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import dynamic from "next/dynamic"; +import { FaUser, FaCog } from "react-icons/fa"; +import TabBar from "../components/TabBar"; +import AcceptPopup from "../components/acceptPopUp"; + +// динамический импорт карты, чтобы не падало на сервере +const MapContainer = dynamic( + () => import("react-leaflet").then((m) => m.MapContainer), + { ssr: false } +); +const TileLayer = dynamic( + () => import("react-leaflet").then((m) => m.TileLayer), + { ssr: false } +); +const Marker = dynamic( + () => import("react-leaflet").then((m) => m.Marker), + { ssr: false } +); +const Popup = dynamic( + () => import("react-leaflet").then((m) => m.Popup), + { ssr: false } +); + +// центр Перми +const DEFAULT_POSITION = [58.0105, 56.2294]; + +const requests = [ + { + id: 1, + title: "Приобрести продукты пенсионерке", + address: "г. Пермь, ул. Ленина 50, кв. 24, этаж 3", + coords: [58.0109, 56.2478], // район ул. Ленина + distance: "1.2 км", + }, + { + id: 2, + title: "Приобрести медикаменты бабушке", + address: "г. Пермь, ул. Пушкина 24, кв. 12, этаж 1", + coords: [58.0135, 56.2320], // район ул. Пушкина + distance: "2.0 км", + }, + { + id: 3, + title: "Сопроводить до поликлиники", + address: "г. Пермь, ул. Куйбышева 95, кв. 7, этаж 2", + coords: [58.0068, 56.2265], // район ул. Куйбышева + distance: "3.4 км", + }, + { + id: 4, + title: "Сопроводить до поликлиники", + address: "г. Пермь, ул. Куйбышева 95, кв. 7, этаж 2", + coords: [58.0068, 56.2265], // район ул. Куйбышева + distance: "3.4 км", + }, + { + id: 5, + title: "Сопроводить до поликлиники", + address: "г. Пермь, ул. Куйбышева 95, кв. 7, этаж 2", + coords: [58.0068, 56.2265], // район ул. Куйбышева + distance: "3.4 км", + }, +]; + + +const MainVolunteerPage = () => { + const [position, setPosition] = useState(DEFAULT_POSITION); + const [hasLocation, setHasLocation] = useState(false); + const [selectedRequest, setSelectedRequest] = useState(null); + const [isPopupOpen, setIsPopupOpen] = useState(false); + + const openPopup = (req) => { + setSelectedRequest(req); + setIsPopupOpen(true); + }; + + const closePopup = () => { + setIsPopupOpen(false); + setSelectedRequest(null); + }; + + useEffect(() => { + if (!navigator.geolocation) return; + navigator.geolocation.getCurrentPosition( + (pos) => { + setPosition([pos.coords.latitude, pos.coords.longitude]); + setHasLocation(true); + }, + () => { + setHasLocation(false); + } + ); + }, []); + + const handleAccept = (req) => { + console.log("Откликнуться на заявку:", req.id); + // TODO: запрос на бэк + }; + + return ( +
+
+ {/* Header */} +
+
+
+ +
+

+ Александр +

+
+ +
+ +

+ Кому нужна помощь +

+ + {/* Карта */} +
+
+ + + {/* Маркер волонтёра */} + {hasLocation && ( + + Вы здесь + + )} + {/* Маркеры заявок */} + {requests.map((req) => ( + + {req.title} + + ))} + +
+
+ + {/* Заявки ниже карты */} +
+ {requests.map((req) => ( +
openPopup(req)} + > +

+ {req.title} +

+

+ {req.address} +

+ {req.distance && ( +

+ Расстояние: {req.distance} +

+ )} + +
+ ))} +
+ + +
+ +
+ + ); +}; + +export default MainVolunteerPage; + diff --git a/app/profileSettings/page.jsx b/app/profileSettings/page.jsx new file mode 100644 index 0000000..78fc86b --- /dev/null +++ b/app/profileSettings/page.jsx @@ -0,0 +1,153 @@ +"use client"; + +import React, { useState } from "react"; +import { useRouter } from "next/navigation"; +import { FaUserCircle } from "react-icons/fa"; +import TabBar from "../components/TabBar"; + +const ProfileSettingsPage = () => { + const router = useRouter(); + + const [avatarUrl, setAvatarUrl] = useState(""); + const [fullName, setFullName] = useState("Иванов Александр Сергеевич"); + const [birthDate, setBirthDate] = useState("1990-03-12"); + const [email, setEmail] = useState("example@mail.com"); + const [phone, setPhone] = useState("+7 (900) 000-00-00"); + + const handleSave = (e) => { + e.preventDefault(); + console.log("Сохранить профиль:", { + avatarUrl, + fullName, + birthDate, + email, + phone, + }); + // здесь будет запрос на бэк + }; + + return ( +
+
+ {/* Header */} +
+ +

+ Настройки профиля +

+ +
+ + {/* Карточка настроек */} +
+ {/* Аватар */} +
+
+ {avatarUrl ? ( + // eslint-disable-next-line @next/next/no-img-element + Аватар + ) : ( + + )} +
+ +
+ +
+ {/* ФИО */} +
+ + setFullName(e.target.value)} + className="w-full rounded-full bg-[#72B8E2] px-4 py-2 text-sm font-montserrat text-white placeholder:text-white/70 outline-none border border-transparent focus:border-white/70" + placeholder="Введите ФИО" + /> +
+ + {/* Дата рождения */} +
+ + setBirthDate(e.target.value)} + className="w-full rounded-full bg-[#72B8E2] px-4 py-2 text-sm font-montserrat text-white outline-none border border-transparent focus:border-white/70" + /> +
+ + {/* Почта */} +
+ + setEmail(e.target.value)} + className="w-full rounded-full bg-[#72B8E2] px-4 py-2 text-sm font-montserrat text-white placeholder:text-white/70 outline-none border border-transparent focus:border-white/70" + placeholder="example@mail.com" + /> +
+ + {/* Телефон */} +
+ + setPhone(e.target.value)} + className="w-full rounded-full bg-[#72B8E2] px-4 py-2 text-sm font-montserrat text:white.placeholder:text-white/70 outline-none border border-transparent focus:border-white/70" + placeholder="+7 (900) 000-00-00" + /> +
+ + {/* Кнопка сохранить */} + +
+
+ + +
+
+ ); +}; + +export default ProfileSettingsPage; diff --git a/package-lock.json b/package-lock.json index b415c65..e83867f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,12 @@ "name": "frontend", "version": "0.1.0", "dependencies": { + "leaflet": "^1.9.4", "next": "16.0.10", "react": "19.2.1", "react-dom": "19.2.1", - "react-icons": "^5.5.0" + "react-icons": "^5.5.0", + "react-leaflet": "^5.0.0" }, "devDependencies": { "@tailwindcss/postcss": "^4", @@ -1227,6 +1229,17 @@ "node": ">=12.4.0" } }, + "node_modules/@react-leaflet/core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz", + "integrity": "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ==", + "license": "Hippocratic-2.1", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4514,6 +4527,12 @@ "node": ">=0.10" } }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5416,6 +5435,20 @@ "dev": true, "license": "MIT" }, + "node_modules/react-leaflet": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-5.0.0.tgz", + "integrity": "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==", + "license": "Hippocratic-2.1", + "dependencies": { + "@react-leaflet/core": "^3.0.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", diff --git a/package.json b/package.json index 5c7c489..1b8a787 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,12 @@ "lint": "eslint" }, "dependencies": { + "leaflet": "^1.9.4", "next": "16.0.10", "react": "19.2.1", "react-dom": "19.2.1", - "react-icons": "^5.5.0" + "react-icons": "^5.5.0", + "react-leaflet": "^5.0.0" }, "devDependencies": { "@tailwindcss/postcss": "^4",