This commit is contained in:
@@ -9,9 +9,20 @@ import {
|
|||||||
} from "@/lib/types";
|
} from "@/lib/types";
|
||||||
import { gql } from "@apollo/client";
|
import { gql } from "@apollo/client";
|
||||||
import { useMutation, useQuery } from "@apollo/client/react";
|
import { useMutation, useQuery } from "@apollo/client/react";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
const GET_EATERY_MENU = gql`{ allEateries { id menuItems { id name } } }`;
|
const GET_EATERY_MENU = gql`
|
||||||
|
query GetEateryMenu {
|
||||||
|
allEateries {
|
||||||
|
id
|
||||||
|
menuItems {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
price
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const ADD_MENU_ITEM = gql`
|
const ADD_MENU_ITEM = gql`
|
||||||
mutation addMenuItem($menuItem: AddMenuItemInput!) {
|
mutation addMenuItem($menuItem: AddMenuItemInput!) {
|
||||||
@@ -30,14 +41,6 @@ function formatPrice(price: number) {
|
|||||||
export default function MenuItemsTab() {
|
export default function MenuItemsTab() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const [menuItems, setMenuItems] = useState<MenuItemEntity[]>([]);
|
const [menuItems, setMenuItems] = useState<MenuItemEntity[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const [showForm, setShowForm] = useState(false);
|
|
||||||
const [newName, setNewName] = useState("");
|
|
||||||
const [newPrice, setNewPrice] = useState("");
|
|
||||||
const [submitting, setSubmitting] = useState(false);
|
|
||||||
const [submitError, setSubmitError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
@@ -45,53 +48,49 @@ export default function MenuItemsTab() {
|
|||||||
error: gqlError,
|
error: gqlError,
|
||||||
} = useQuery<allEateriesQuery>(GET_EATERY_MENU, {
|
} = useQuery<allEateriesQuery>(GET_EATERY_MENU, {
|
||||||
client: eateryClient,
|
client: eateryClient,
|
||||||
fetchPolicy: "no-cache",
|
fetchPolicy: "network-only",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [mutateAddMenuItem] = useMutation<addMenuItemMutation>(ADD_MENU_ITEM, {
|
||||||
|
client: eateryClient,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [showForm, setShowForm] = useState(false);
|
||||||
|
const [newName, setNewName] = useState("");
|
||||||
|
const [newPrice, setNewPrice] = useState("");
|
||||||
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
const [submitError, setSubmitError] = useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
if (data?.allEateries?.[0]) {
|
||||||
setError(null);
|
setMenuItems(data.allEateries[0].menuItems);
|
||||||
|
|
||||||
if (!gqlLoading) {
|
|
||||||
if (data) setMenuItems(data.allEateries[0].menuItems);
|
|
||||||
else
|
|
||||||
setError(
|
|
||||||
gqlError?.message ||
|
|
||||||
"Không thể tải dữ liệu menu. Kiểm tra kết nối backend.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}, [data]);
|
||||||
setLoading(false);
|
|
||||||
}, [data, gqlLoading, gqlError]);
|
|
||||||
|
|
||||||
const handleAdd = async (e: React.FormEvent) => {
|
const handleAdd = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!newName.trim() || !newPrice) return;
|
if (!newName.trim() || !newPrice) return;
|
||||||
|
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
setSubmitError(null);
|
setSubmitError(null);
|
||||||
try {
|
|
||||||
const [addMenuItem, { data }] = useMutation<addMenuItemMutation>(
|
|
||||||
GET_EATERY_MENU,
|
|
||||||
{
|
|
||||||
client: eateryClient,
|
|
||||||
fetchPolicy: "no-cache",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await addMenuItem({
|
try {
|
||||||
|
const { data: mutationResult } = await mutateAddMenuItem({
|
||||||
variables: {
|
variables: {
|
||||||
|
menuItem: {
|
||||||
name: newName,
|
name: newName,
|
||||||
price: newPrice,
|
price: parseFloat(newPrice),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data) setMenuItems((prev) => [...prev, data.addMenuItem]);
|
if (mutationResult?.addMenuItem) {
|
||||||
|
setMenuItems((prev) => [...prev, mutationResult.addMenuItem]);
|
||||||
setNewName("");
|
closeForm();
|
||||||
setNewPrice("");
|
}
|
||||||
setShowForm(false);
|
} catch (err: any) {
|
||||||
} catch {
|
console.error("Mutation Error:", err);
|
||||||
setSubmitError("Không thể thêm món. Vui lòng thử lại.");
|
setSubmitError(err.message || "Không thể thêm món. Vui lòng thử lại.");
|
||||||
} finally {
|
} finally {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
}
|
}
|
||||||
@@ -104,23 +103,14 @@ export default function MenuItemsTab() {
|
|||||||
setNewPrice("");
|
setNewPrice("");
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (gqlLoading && menuItems.length === 0)
|
||||||
|
return <div className="py-16 text-center">Đang tải menu...</div>;
|
||||||
|
if (gqlError)
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center py-16 text-(--color-text-muted)">
|
<div className="py-16 text-center text-red-500">
|
||||||
<i className="fa-solid fa-spinner mr-2 animate-spin"></i>
|
Lỗi: {gqlError.message}
|
||||||
Đang tải menu...
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-center justify-center py-16 text-red-500">
|
|
||||||
<i className="fa-solid fa-circle-exclamation mb-2 text-2xl"></i>
|
|
||||||
<p className="text-sm">{error}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user