VolonteurMainPage
This commit is contained in:
202
app/mainValounter/page.jsx
Normal file
202
app/mainValounter/page.jsx
Normal file
@@ -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 (
|
||||
<div className="min-h-screen w-full bg-[#90D2F9] flex justify-center px-4">
|
||||
<div className="relative w-full max-w-md flex flex-col pb-20 pt-4">
|
||||
{/* Header */}
|
||||
<header className="flex items-center justify-between mb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-8 h-8 rounded-full border border-white flex items-center justify-center">
|
||||
<FaUser className="text-white text-sm" />
|
||||
</div>
|
||||
<p className="font-montserrat font-extrabold text-[11px] leading-[11px] text-white">
|
||||
Александр
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="w-8 h-8 rounded-full border border-white flex items-center justify-center"
|
||||
>
|
||||
<FaCog className="text-white text-sm" />
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<h1 className="font-montserrat font-extrabold text-[16px] leading-[20px] text-white mb-2">
|
||||
Кому нужна помощь
|
||||
</h1>
|
||||
|
||||
{/* Карта */}
|
||||
<div className="w-full bg-transparent mb-3">
|
||||
<div className="w-full h-[250px] bg-[#D9D9D9] rounded-2xl overflow-hidden">
|
||||
<MapContainer
|
||||
center={position}
|
||||
zoom={13}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© OpenStreetMap contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
{/* Маркер волонтёра */}
|
||||
{hasLocation && (
|
||||
<Marker position={position}>
|
||||
<Popup>Вы здесь</Popup>
|
||||
</Marker>
|
||||
)}
|
||||
{/* Маркеры заявок */}
|
||||
{requests.map((req) => (
|
||||
<Marker key={req.id} position={req.coords}>
|
||||
<Popup>{req.title}</Popup>
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Заявки ниже карты */}
|
||||
<main className="space-y-3">
|
||||
{requests.map((req) => (
|
||||
<div
|
||||
key={req.id}
|
||||
className="bg-white rounded-xl px-3 py-2 flex flex-col gap-1"
|
||||
onClick={() => openPopup(req)}
|
||||
>
|
||||
<p className="font-montserrat font-semibold text-[12px] leading-[14px] text-black">
|
||||
{req.title}
|
||||
</p>
|
||||
<p className="font-montserrat text-[10px] text-black">
|
||||
{req.address}
|
||||
</p>
|
||||
{req.distance && (
|
||||
<p className="font-montserrat text-[9px] text-gray-500">
|
||||
Расстояние: {req.distance}
|
||||
</p>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleAccept(req)}
|
||||
className="mt-2 w-full bg-[#94E067] rounded-lg py-2 flex items-center justify-center"
|
||||
>
|
||||
<span className="font-montserrat font-bold text-[14px] text-white">
|
||||
Откликнуться
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</main>
|
||||
|
||||
<TabBar />
|
||||
</div>
|
||||
<AcceptPopup
|
||||
request={selectedRequest}
|
||||
isOpen={isPopupOpen}
|
||||
onClose={closePopup}
|
||||
onAccept={handleAccept}
|
||||
/>
|
||||
</div>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default MainVolunteerPage;
|
||||
|
||||
Reference in New Issue
Block a user