menu and categories api , add map
This commit is contained in:
parent
82d80c2d7b
commit
400a916541
|
|
@ -11,6 +11,7 @@ node_modules
|
||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
|
.env
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -10,13 +10,18 @@
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@neshan-maps-platform/leaflet": "^1.0.8",
|
||||||
"@reduxjs/toolkit": "^2.11.2",
|
"@reduxjs/toolkit": "^2.11.2",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"framer-motion": "^12.23.26",
|
"framer-motion": "^12.23.26",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
|
"mapbox-gl": "^3.17.0",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
|
"react-leaflet": "^5.0.0",
|
||||||
|
"react-map-gl": "^8.1.0",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^7.9.4",
|
"react-router-dom": "^7.9.4",
|
||||||
"recharts": "^3.6.0",
|
"recharts": "^3.6.0",
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ import coffee05 from "../../assets/image/coffee05.png";
|
||||||
import coffee06 from "../../assets/image/coffee06.png";
|
import coffee06 from "../../assets/image/coffee06.png";
|
||||||
import defaultuser from "../../assets/image/defaultuser.jpg";
|
import defaultuser from "../../assets/image/defaultuser.jpg";
|
||||||
|
|
||||||
|
import { MapPicker } from "./map/map.jsx";
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
import cafeService from "../../services/cafe";
|
import cafeService from "../../services/cafe";
|
||||||
|
|
||||||
|
|
@ -98,6 +100,7 @@ export default function EditCafe() {
|
||||||
const [newCategory, setNewCategory] = useState("");
|
const [newCategory, setNewCategory] = useState("");
|
||||||
const [editingIndex, setEditingIndex] = useState(null);
|
const [editingIndex, setEditingIndex] = useState(null);
|
||||||
const [editValue, setEditValue] = useState("");
|
const [editValue, setEditValue] = useState("");
|
||||||
|
const [location, setLocation] = useState({lat: 32.64762831857033, lng: 51.71143696482368});
|
||||||
|
|
||||||
// Effects
|
// Effects
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -170,6 +173,8 @@ export default function EditCafe() {
|
||||||
setEditValue("");
|
setEditValue("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("Cafe location:", location);
|
||||||
|
|
||||||
// Render States
|
// Render States
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -200,7 +205,7 @@ export default function EditCafe() {
|
||||||
return (
|
return (
|
||||||
<section dir="rtl" className="w-full overflow-x-hidden">
|
<section dir="rtl" className="w-full overflow-x-hidden">
|
||||||
{editmenu ? (
|
{editmenu ? (
|
||||||
<EditCafeMenu setEditMenu={setEditMenu} />
|
<EditCafeMenu setEditMenu={setEditMenu} id={id} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<style>{`
|
<style>{`
|
||||||
|
|
@ -475,6 +480,13 @@ export default function EditCafe() {
|
||||||
<p>29 دیدگاه</p>{" "}
|
<p>29 دیدگاه</p>{" "}
|
||||||
<p className="font-bold text-text1">مشاهده بیشتر</p>{" "}
|
<p className="font-bold text-text1">مشاهده بیشتر</p>{" "}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<MapPicker
|
||||||
|
value={location}
|
||||||
|
onChange={setLocation}
|
||||||
|
className="h-[400px] w-full rounded-xl mt-10"
|
||||||
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,75 @@
|
||||||
import { useState } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { CgAddR } from "react-icons/cg";
|
import { CgAddR } from "react-icons/cg";
|
||||||
import { PiCoffee } from "react-icons/pi";
|
import { PiCoffee } from "react-icons/pi";
|
||||||
import { FaRegEdit } from "react-icons/fa";
|
import { FaRegEdit } from "react-icons/fa";
|
||||||
import CoffeeCard from "./Component/CoffeeCard";
|
import CoffeeCard from "./Component/CoffeeCard";
|
||||||
import coffee12 from "../../assets/image/coffee12.png";
|
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 [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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -70,20 +101,19 @@ export default function EditCafeMenu({ setEditMenu }) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex mr-6 gap-4 relative">
|
<div className="flex mr-6 gap-4 relative">
|
||||||
{DEFAULT_CATEGORIES.map((cat, index) => (
|
{categories.map((cat, index) => (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => setSelectedCategory(cat)}
|
onClick={() => { setSelectedCategory(cat), setSelectedCatId(cat._id) }}
|
||||||
className={`relative -bottom-[2px] pb-2 text-sm md:text-base transition-all
|
className={`relative -bottom-[2px] pb-2 text-sm md:text-base transition-all
|
||||||
${
|
${selectedCatId === cat?._id
|
||||||
selectedCategory === cat
|
? "text-text1 font-bold"
|
||||||
? "text-text1 font-bold"
|
: "text-gray-400 hover:text-text1"
|
||||||
: "text-gray-400 hover:text-text1"
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{cat}
|
{cat?.name}
|
||||||
|
|
||||||
{selectedCategory === cat && (
|
{selectedCatId === cat?._id && (
|
||||||
<span
|
<span
|
||||||
className="absolute left-0 -bottom-[9px] w-full h-[5px]
|
className="absolute left-0 -bottom-[9px] w-full h-[5px]
|
||||||
bg-border rounded-full transition-all duration-300"
|
bg-border rounded-full transition-all duration-300"
|
||||||
|
|
@ -100,16 +130,17 @@ export default function EditCafeMenu({ setEditMenu }) {
|
||||||
<CgAddR />
|
<CgAddR />
|
||||||
افزودن زیر عنوان
|
افزودن زیر عنوان
|
||||||
</div>
|
</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} />
|
<FaRegEdit size={30} />
|
||||||
<PiCoffee size={30} />
|
<PiCoffee size={30} />
|
||||||
<p className="border-b-2 border-border">قهوه ها</p>
|
<p className="border-b-2 border-border">{selectedCategory?.name}</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{PRODUCTS.map((item) => (
|
{items.map((item) => (
|
||||||
<CoffeeCard
|
<CoffeeCard
|
||||||
key={item.id}
|
key={item?._id}
|
||||||
title={item.title}
|
title={item?.title}
|
||||||
description={item.description}
|
description={item.description}
|
||||||
price={item.price}
|
price={item.price}
|
||||||
image={item.image}
|
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}`),
|
getCafeById: (id) => requests.get(`/cafe/v1/get-cafe-profile-by-cafe/${id}`),
|
||||||
|
|
||||||
editCafe: (cafeData) => requests.put(`/cafe/v1/edit-cafe-profile-by-admin`, cafeData),
|
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),
|
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;
|
export default cafeService;
|
||||||
Loading…
Reference in New Issue