Skip to content

Commit

Permalink
Merge pull request #59 from NextCafeteria/feature/swr-cont
Browse files Browse the repository at this point in the history
refactor SWR for data fetching
  • Loading branch information
vietanhdev committed Aug 6, 2023
2 parents 88b289c + 0e7f1d2 commit f65140e
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 202 deletions.
137 changes: 75 additions & 62 deletions src/app/[lng]/dashboard/products/product-details/[productId]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { useEffect, useState } from "react";
import { useTranslation } from "@/app/i18n/client";
import { useRouter } from "next/navigation";
import { GetProduct, UpdateProduct } from "@/lib/requests/products";
import { useGetProduct, UpdateProduct } from "@/lib/requests/products";
import { useSession } from "next-auth/react";
import Image from "next/image";
import Skeleton from "react-loading-skeleton";
Expand All @@ -19,38 +19,44 @@ export default function ({ params: { lng, productId } }) {
router.push(`/${lng}/login`);
}

const [productData, setProductData] = useState(null);
const [isUpdatingImage, setIsUpdatingImage] = useState(false);
const [updateImageProgress, setUpdateProgress] = useState(0);

const refetchProductData = () => {
GetProduct(productId).then((productData) => {
setProductData(productData);
}).catch((e) => {
console.log(e);
alert("Could not get product");
});
};

useEffect(() => {
refetchProductData();
}, []);
const { product, error, isLoading, mutateProduct } = useGetProduct(productId);
if (isLoading) console.log("loading");
if (error) {
console.log(error);
alert("Could not get product");
router.push(`/${lng}/dashboard/products`);
}
const setProductData = function (productData) {
mutateProduct(productData, {revalidate: false});
};

const updateProductCustomization = (customizationId, customizationData) => {
let productDataCopy = { ...productData };
if (customizationData === null) {
delete productDataCopy.customizations[customizationId];
setProductData(productDataCopy);
return;
if(customizationData === null) {
const customizationsCopy = {...product.customizations};
delete customizationsCopy[customizationId];
setProductData({
...product,
customizations: customizationsCopy,
});
}
else {
setProductData({
...product,
customizations: {
...product.customizations,
[customizationId]: customizationData,
},
});
}
productDataCopy.customizations[customizationId] = customizationData;
setProductData(productDataCopy);
};

const handleSaveProduct = () => {
UpdateProduct(
productId,
productData,
product,
).then(() => {
alert("Product updated");
router.push(`/${lng}/dashboard/products`);
Expand All @@ -69,64 +75,71 @@ export default function ({ params: { lng, productId } }) {
<div className="pb-3 pt-2 border-b-2 border-gray-800">
<div className="flex w-full text-2xl px-2">
<BackButton href={`/${lng}/dashboard/products`} />
{t("Product")}: {productData?.name}
{t("Product")}: {product?.name}
</div>
</div>

<div className="flex flex-row w-full my-2 mx-1 rounded-md">

{
isLoading ? (
<div className="flex flex-col items-center justify-center w-full h-[500px]">
loading...
</div>
) : (
<div className="flex flex-row w-full my-2 mx-1 rounded-md">
<div className="flex flex-col items-begin justify-center w-full relative">
<p className="text-md font-bold">{t("Name")}</p>
<input
type="text"
className="w-full border-[1px] border-gray-600 rounded-md p-2 mb-2"
value={productData?.name}
value={product?.name}
onChange={(e) => {
let productDataCopy = { ...productData };
productDataCopy.name = e.target.value;
setProductData(productDataCopy);
mutateProduct({ ...product,
name: e.target.value }, {revalidate: false});
}}
/>
<p className="text-md font-bold">{t("Description")}</p>
<input
type="text"
className="w-full border-[1px] border-gray-600 rounded-md p-2 mb-2"
value={productData?.description}
value={product?.description}
onChange={(e) => {
let productDataCopy = { ...productData };
productDataCopy.description = e.target.value;
setProductData(productDataCopy);
mutateProduct({ ...product,
description: e.target.value }, {revalidate: false});
}}
/>
<p className="text-md font-bold">{t("Price")}</p>
<input
type="number"
className="w-full border-[1px] border-gray-600 rounded-md p-2 mb-2"
value={productData?.price}
value={product?.price}
onChange={(e) => {
let productDataCopy = { ...productData };
productDataCopy.price = parseFloat(e.target.value);
setProductData(productDataCopy);
mutateProduct({ ...product,
price: parseFloat(e.target.value) }, {revalidate: false});
}}
/>
</div>

<div className="rounded-md w-[200px] justify-center align-middle items-center relative overflow-hidden border-[1px] m-2 border-gray-600 h-fit pb-[30px]">
{isUpdatingImage ? (
{
isUpdatingImage ? (
<div className="flex absolute left-0 bottom-0 bg-gray-100 w-20 h-10 opacity-70 transition-opacity duration-[0.2s] ease-[ease-in-out] content-center items-center">
{updateImageProgress + "%"}
</div>
) : (
productData?.image ? (
) :
(
product?.image ? (
<Image
alt={productData?.name}
src={productData?.image}
alt={product?.name}
src={product?.image}
width={200}
height={200}
className="overflow-hidden shadow-md w-[200px] h-auto"
/>) : (
<Skeleton width={200} height={100} />
)
)}
)
}

<ImageUploader
styles="absolute left-0 bottom-0 bg-gray-100 w-full h-[30px] duration-[0.2s] ease-[ease-in-out]"
Expand All @@ -135,50 +148,50 @@ export default function ({ params: { lng, productId } }) {
}}
handleUploadSuccess={(url) => {
setIsUpdatingImage(false);
let productDataCopy = { ...productData };
productDataCopy.image = url;
setProductData(productDataCopy);
setProductData({...product, image: url});
}}
handleUploadProgress={(progress) => {
setUpdateProgress(progress);
}}
/>
</div>
</div>
)
}


{productData?.customizations && Object.keys(productData?.customizations).sort(
{product?.customizations && Object.keys(product?.customizations).sort(
(a, b) => {
a.order - b.order;
}
).map((customizationId, id) => (
<CustomizationCard
key={customizationId}
id={customizationId}
customization={...productData?.customizations[customizationId]}
customization={...product?.customizations[customizationId]}
lng={lng}
updateCustomization={updateProductCustomization}
/>
))}
{(productData?.customizations && !Object.keys(productData?.customizations).length) && (
{(product?.customizations && !Object.keys(product?.customizations).length) && (
<p className="text-sm">
{t("Add a customization by clicking the button below.")}
</p>
)}
<button type="button" className="focus:outline-none bg-green-600 text-white hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2 mr-2 mb-2:bg-red-700 w-full mt-1"
onClick={() => {
let productDataCopy = { ...productData };
if (!productDataCopy.customizations) {
productDataCopy.customizations = {};
}
let customizationId = uuidv4();
productDataCopy.customizations[customizationId] = {
order: Math.max(...Object.keys(productDataCopy.customizations).map((customizationId) => productDataCopy.customizations[customizationId].order)) + 1,
name: "",
description: "",
price: 0,
options: {},
};
setProductData(productDataCopy);
setProductData({ ...product,
customizations: {
...product?.customizations,
[uuidv4()]: {
order: Math.max(...Object.keys(product?.customizations).map((customizationId) => product?.customizations[customizationId].order)) + 1,
name: "",
description: "",
price: 0,
options: {},
},
},
});
}}
>
{ t("Add Customization") }
Expand All @@ -194,4 +207,4 @@ export default function ({ params: { lng, productId } }) {
</div>
</main>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useSession } from "next-auth/react";
import Rating from "@/components/Rating";
import BackButton from "@/components/buttons/BackButton";

import { GetStore, AddStaff } from "@/lib/requests/stores";
import { useGetStore, AddStaff } from "@/lib/requests/stores";

export default function NewStores({ params: { lng, storeId } }) {
const router = useRouter();
Expand All @@ -16,20 +16,13 @@ export default function NewStores({ params: { lng, storeId } }) {
router.push(`/${lng}/login`);
}

const [storeData, setstoreData] = useState(null);
useEffect(() => {
GetStore(
storeId,
(data) => {
setstoreData(data);
},
(e) => {
console.log(e);
alert("Could not get stores");
router.push(`/${lng}/dashboard/stores`);
}
);
}, []);
const { store, error, isLoading } = useGetStore(storeId);

if (error) {
console.log(error);
alert("Could not get store");
router.push(`/${lng}/dashboard/stores`);
}

const [email, setEmail] = useState("");
const [role, setRole] = useState("staff");
Expand All @@ -41,14 +34,14 @@ export default function NewStores({ params: { lng, storeId } }) {
<div className="pb-3 pt-2 border-b-2 border-gray-800">
<div className="flex w-full bstore-b-2 bstore-gray-800 text-2xl px-2">
<BackButton href={`/${lng}/dashboard/stores`} />
{t("Store")}: {storeData?.name}
{t("Store")}: {store?.name}
</div>
<div className="flex flex-col items-left w-full pl-[50px] text-sm">
{storeData?.address} - {storeData?.phone}
{store?.address} - {store?.phone}
</div>
<div className="flex flex-row items-left w-full pl-[50px] text-sm">
<Rating value={storeData?.rating} /> {" "} {storeData?.rating}/5{" "}
{t("stars")} - {storeData?.totalRatingTimes || 0} {t("reviews")}
<Rating value={store?.rating} /> {" "} {store?.rating}/5{" "}
{t("stars")} - {store?.totalRatingTimes || 0} {t("reviews")}
</div>
</div>
<div className="flex flex-col items-center justify-center w-full p-2 min-h-[100px] my-1 mx-0 rounded-md">
Expand Down
Loading

0 comments on commit f65140e

Please sign in to comment.