menu and categories api , add map
This commit is contained in:
parent
82d80c2d7b
commit
400a916541
|
|
@ -11,6 +11,7 @@ node_modules
|
|||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.env
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -10,13 +10,18 @@
|
|||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@neshan-maps-platform/leaflet": "^1.0.8",
|
||||
"@reduxjs/toolkit": "^2.11.2",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
"axios": "^1.13.2",
|
||||
"framer-motion": "^12.23.26",
|
||||
"leaflet": "^1.9.4",
|
||||
"mapbox-gl": "^3.17.0",
|
||||
"react": "^19.1.1",
|
||||
"react-dom": "^19.1.1",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-leaflet": "^5.0.0",
|
||||
"react-map-gl": "^8.1.0",
|
||||
"react-redux": "^9.2.0",
|
||||
"react-router-dom": "^7.9.4",
|
||||
"recharts": "^3.6.0",
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ import coffee05 from "../../assets/image/coffee05.png";
|
|||
import coffee06 from "../../assets/image/coffee06.png";
|
||||
import defaultuser from "../../assets/image/defaultuser.jpg";
|
||||
|
||||
import { MapPicker } from "./map/map.jsx";
|
||||
|
||||
// Services
|
||||
import cafeService from "../../services/cafe";
|
||||
|
||||
|
|
@ -98,6 +100,7 @@ export default function EditCafe() {
|
|||
const [newCategory, setNewCategory] = useState("");
|
||||
const [editingIndex, setEditingIndex] = useState(null);
|
||||
const [editValue, setEditValue] = useState("");
|
||||
const [location, setLocation] = useState({lat: 32.64762831857033, lng: 51.71143696482368});
|
||||
|
||||
// Effects
|
||||
useEffect(() => {
|
||||
|
|
@ -170,6 +173,8 @@ export default function EditCafe() {
|
|||
setEditValue("");
|
||||
};
|
||||
|
||||
console.log("Cafe location:", location);
|
||||
|
||||
// Render States
|
||||
if (loading) {
|
||||
return (
|
||||
|
|
@ -200,7 +205,7 @@ export default function EditCafe() {
|
|||
return (
|
||||
<section dir="rtl" className="w-full overflow-x-hidden">
|
||||
{editmenu ? (
|
||||
<EditCafeMenu setEditMenu={setEditMenu} />
|
||||
<EditCafeMenu setEditMenu={setEditMenu} id={id} />
|
||||
) : (
|
||||
<>
|
||||
<style>{`
|
||||
|
|
@ -475,6 +480,13 @@ export default function EditCafe() {
|
|||
<p>29 دیدگاه</p>{" "}
|
||||
<p className="font-bold text-text1">مشاهده بیشتر</p>{" "}
|
||||
</div>
|
||||
|
||||
<MapPicker
|
||||
value={location}
|
||||
onChange={setLocation}
|
||||
className="h-[400px] w-full rounded-xl mt-10"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,44 +1,75 @@
|
|||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { CgAddR } from "react-icons/cg";
|
||||
import { PiCoffee } from "react-icons/pi";
|
||||
import { FaRegEdit } from "react-icons/fa";
|
||||
import CoffeeCard from "./Component/CoffeeCard";
|
||||
import coffee12 from "../../assets/image/coffee12.png";
|
||||
import cafeService from "../../services/cafe";
|
||||
|
||||
const DEFAULT_CATEGORIES = [
|
||||
"نوشیدنی سرد",
|
||||
"نوشیدنی گرم",
|
||||
"کیک و دسر",
|
||||
"صبحانه",
|
||||
"ساندویچ و برگر",
|
||||
"سالاد و پیش غذا",
|
||||
];
|
||||
const PRODUCTS = [
|
||||
{
|
||||
id: 1,
|
||||
title: "اسپرسو",
|
||||
description: "قهوه 100٪ عربیکا با عطر بالا",
|
||||
price: "118,000",
|
||||
image: coffee12,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "لاته",
|
||||
description: "شیر بخار داده شده + اسپرسو",
|
||||
price: "135,000",
|
||||
image: coffee12,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "کاپوچینو",
|
||||
description: "کلاسیک ایتالیایی با فوم شیر",
|
||||
price: "142,000",
|
||||
image: coffee12,
|
||||
},
|
||||
];
|
||||
|
||||
export default function EditCafeMenu({ setEditMenu }) {
|
||||
|
||||
export default function EditCafeMenu({ setEditMenu, id }) {
|
||||
const [selectedCategory, setSelectedCategory] = useState(null);
|
||||
const [selectedCatId, setSelectedCatId] = useState(null);
|
||||
const [categories, setCategories] = useState([]);
|
||||
const [items, setItems] = useState([]);
|
||||
|
||||
const getMenuItems = async () => {
|
||||
const params = { cafeId: id };
|
||||
try {
|
||||
const response = await cafeService.getMenuItems(params);
|
||||
const data = response.data?.data?.docs || [];
|
||||
|
||||
////find categories////
|
||||
const categoryList = data.map(item => item?.category);
|
||||
const uniqueCategories = Array.from(
|
||||
new Map(categoryList.map(item => [item?._id, item])).values()
|
||||
);
|
||||
setCategories(uniqueCategories);
|
||||
// console.log("Categories:", uniqueCategories);
|
||||
|
||||
////find categories////
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error fetching menu items:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// فقط یک بار در mount
|
||||
useEffect(() => {
|
||||
getMenuItems();
|
||||
}, [id]);
|
||||
|
||||
// وقتی categories تغییر میکند، default category رو set کن
|
||||
useEffect(() => {
|
||||
if (categories.length > 0) {
|
||||
const defaultCategory = categories[0] || categories[0] || null;
|
||||
setSelectedCatId(defaultCategory?._id);
|
||||
setSelectedCategory(defaultCategory);
|
||||
}
|
||||
}, [categories]);
|
||||
|
||||
|
||||
const getItemsByCategory = async (categoryId) => {
|
||||
const params = {
|
||||
cafeId: id,
|
||||
categoryInput: selectedCategory?._id
|
||||
};
|
||||
try {
|
||||
const response = await cafeService.getItemsByCategory(params);
|
||||
setItems(response.data?.data?.docs || []);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error fetching items by category:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// وقتی selectedCategory تغییر میکند، items رو fetch کن
|
||||
useEffect(() => {
|
||||
if (selectedCategory) {
|
||||
getItemsByCategory();
|
||||
}
|
||||
}, [selectedCategory]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
|
@ -70,20 +101,19 @@ export default function EditCafeMenu({ setEditMenu }) {
|
|||
</div>
|
||||
|
||||
<div className="flex mr-6 gap-4 relative">
|
||||
{DEFAULT_CATEGORIES.map((cat, index) => (
|
||||
{categories.map((cat, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setSelectedCategory(cat)}
|
||||
onClick={() => { setSelectedCategory(cat), setSelectedCatId(cat._id) }}
|
||||
className={`relative -bottom-[2px] pb-2 text-sm md:text-base transition-all
|
||||
${
|
||||
selectedCategory === cat
|
||||
${selectedCatId === cat?._id
|
||||
? "text-text1 font-bold"
|
||||
: "text-gray-400 hover:text-text1"
|
||||
}`}
|
||||
>
|
||||
{cat}
|
||||
{cat?.name}
|
||||
|
||||
{selectedCategory === cat && (
|
||||
{selectedCatId === cat?._id && (
|
||||
<span
|
||||
className="absolute left-0 -bottom-[9px] w-full h-[5px]
|
||||
bg-border rounded-full transition-all duration-300"
|
||||
|
|
@ -100,16 +130,17 @@ export default function EditCafeMenu({ setEditMenu }) {
|
|||
<CgAddR />
|
||||
افزودن زیر عنوان
|
||||
</div>
|
||||
<div className="flex font-bold items-center text-center gap-2 mt-4">
|
||||
<div className="flex font-bold items-center text-center gap-2 my-4">
|
||||
<FaRegEdit size={30} />
|
||||
<PiCoffee size={30} />
|
||||
<p className="border-b-2 border-border">قهوه ها</p>
|
||||
<p className="border-b-2 border-border">{selectedCategory?.name}</p>
|
||||
|
||||
</div>
|
||||
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{PRODUCTS.map((item) => (
|
||||
{items.map((item) => (
|
||||
<CoffeeCard
|
||||
key={item.id}
|
||||
title={item.title}
|
||||
key={item?._id}
|
||||
title={item?.title}
|
||||
description={item.description}
|
||||
price={item.price}
|
||||
image={item.image}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import L from '@neshan-maps-platform/leaflet';
|
||||
import '@neshan-maps-platform/leaflet/dist/leaflet.css';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const MapPicker = ({ value, onChange, className }) => {
|
||||
useEffect(() => {
|
||||
const map = new L.Map("map", {
|
||||
key: import.meta.env.VITE_NESHAN_API_KEY,
|
||||
maptype: "neshan",
|
||||
poi: false,
|
||||
traffic: false,
|
||||
center: value
|
||||
// || [32.64762831857033, 51.71143696482368]
|
||||
,
|
||||
zoom: 14,
|
||||
});
|
||||
let marker;
|
||||
|
||||
if (value) {
|
||||
marker = L.marker(value).addTo(map);
|
||||
}
|
||||
map.on('click', function(e) {
|
||||
const { lat, lng } = e.latlng;
|
||||
if (marker) {
|
||||
map.removeLayer(marker);
|
||||
}
|
||||
marker = L.marker([lat, lng]).addTo(map);
|
||||
onChange([lat, lng]);
|
||||
});
|
||||
|
||||
return () => {
|
||||
map.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="map" className={`${className}`}></div>
|
||||
);
|
||||
}
|
||||
|
|
@ -5,9 +5,16 @@ const cafeService = {
|
|||
getCafeById: (id) => requests.get(`/cafe/v1/get-cafe-profile-by-cafe/${id}`),
|
||||
|
||||
editCafe: (cafeData) => requests.put(`/cafe/v1/edit-cafe-profile-by-admin`, cafeData),
|
||||
editMenu: (menuData) => requests.put(`/cafe/v1/edit-menu-items`, menuData),
|
||||
|
||||
|
||||
getMenuItems: (params) => requests.getByParams(`/cafemenu/get-menu-category-items`, params),
|
||||
getItemsByCategory: (params) => requests.getByParams(`/cafemenu/get-menu-items`, params),
|
||||
|
||||
addMenuItem: (itemData) => requests.post(`/cafemenu/create-cafe-menu`, itemData),
|
||||
editMenu: (menuData) => requests.put(`/cafe/v1/edit-menu-items`, menuData),
|
||||
|
||||
addCategory: (categoryData) => requests.post(`/cafemenu/add-category`, categoryData),
|
||||
|
||||
};
|
||||
|
||||
export default cafeService;
|
||||
Loading…
Reference in New Issue