From 8153e775529f5df3a042c507f1c8309f35c1dbc7 Mon Sep 17 00:00:00 2001 From: nguyenvanhadncntt Date: Thu, 19 Sep 2024 15:20:05 +0700 Subject: [PATCH] #1034 update promotion page --- backoffice/common/items/Input.tsx | 3 +- .../components/MultipleAutoComplete.tsx | 3 +- .../PromotionGeneralInformation.tsx | 37 +++-- .../modules/promotion/models/Promotion.ts | 8 +- .../promotion/services/PromotionService.ts | 6 +- .../promotion/manager-promotion/[id]/edit.tsx | 131 ++++++++++++++++++ .../promotion/manager-promotion/create.tsx | 5 +- .../promotion/manager-promotion/index.tsx | 7 +- 8 files changed, 177 insertions(+), 23 deletions(-) create mode 100644 backoffice/pages/promotion/manager-promotion/[id]/edit.tsx diff --git a/backoffice/common/items/Input.tsx b/backoffice/common/items/Input.tsx index 8e15f77c04..8767395b68 100644 --- a/backoffice/common/items/Input.tsx +++ b/backoffice/common/items/Input.tsx @@ -153,7 +153,6 @@ export const Select = ({ id={field} className={`form-select ${error ? 'border-danger' : ''}`} {...register(field, registerOptions)} - defaultValue={defaultValue} disabled={disabled} multiple={isMultiple} onChange={onChange} @@ -162,7 +161,7 @@ export const Select = ({ {placeholder} {options.map((item) => ( - ))} diff --git a/backoffice/modules/promotion/components/MultipleAutoComplete.tsx b/backoffice/modules/promotion/components/MultipleAutoComplete.tsx index a7e327e004..539a6a1e4b 100644 --- a/backoffice/modules/promotion/components/MultipleAutoComplete.tsx +++ b/backoffice/modules/promotion/components/MultipleAutoComplete.tsx @@ -14,11 +14,12 @@ type props = { onRemoveElement: (value: any) => void; optionSelectedIds: number[]; isSubmitting: boolean; + addedOptions?: any[]; }; const MultipleAutoComplete = (props: props) => { const [isFocusing, setIsFocusing] = useState(false); - const [optionSelecteds, setOptionSelecteds] = useState([]); + const [optionSelecteds, setOptionSelecteds] = useState(props.addedOptions ?? []); const queryData = (query: string) => { props.fetchOptions(query); }; diff --git a/backoffice/modules/promotion/components/PromotionGeneralInformation.tsx b/backoffice/modules/promotion/components/PromotionGeneralInformation.tsx index d46807dea5..0daa846fa3 100644 --- a/backoffice/modules/promotion/components/PromotionGeneralInformation.tsx +++ b/backoffice/modules/promotion/components/PromotionGeneralInformation.tsx @@ -25,15 +25,32 @@ const PromotionGeneralInformation = ({ const [discountType, setDiscountType] = useState(promotion?.discountType); const [usageType, setUsageType] = useState(promotion?.usageType); const [applyTo, setApplyTo] = useState(promotion?.applyTo); - const [brands, setBrands] = useState(promotion?.brands.map((brand) => brand.id) ?? []); + const [brands, setBrands] = useState(promotion?.brands?.map((brand) => brand.id) ?? []); const [categories, setCategories] = useState( - promotion?.categories.map((category) => category.id) ?? [] + promotion?.categories?.map((category) => category.id) ?? [] ); - const [products, setProducts] = useState(promotion?.products.map((product) => product.id) ?? []); + const [products, setProducts] = useState(promotion?.products?.map((product) => product.id) ?? []); const [productVms, setProductVms] = useState(promotion?.products ?? []); const [brandVms, setBrandVms] = useState(promotion?.brands ?? []); const [categoryVms, setCategoryVms] = useState(promotion?.categories ?? []); + useEffect(() => { + if (promotion) { + setDiscountType(promotion.discountType); + setUsageType(promotion.usageType); + setApplyTo(promotion.applyTo); + + setProducts(promotion.products?.map((product) => product.id) ?? []); + setProductVms(promotion.products ?? []); + + setBrands(promotion.brands?.map((brand) => brand.id) ?? []); + setBrandVms(promotion.brands ?? []); + + setCategories(promotion.categories?.map((category) => category.id) ?? []); + setCategoryVms(promotion.categories ?? []); + } + }, [promotion]); + useEffect(() => { if (applyTo === 'PRODUCT') { searchProducts('').then((data) => { @@ -45,10 +62,13 @@ const PromotionGeneralInformation = ({ const convertDateToString = (date?: Date | string) => { if (date) { if (typeof date === 'string') { - return date; + date = new Date(date); } const month = date.getMonth() + 1; - return `${date.getFullYear()}-${month > 9 ? month : '0' + month}-${date.getDate()}`; + const dateInMonth = date.getDate(); + return `${date.getFullYear()}-${month > 9 ? month : '0' + month}-${ + dateInMonth > 9 ? dateInMonth : '0' + dateInMonth + }`; } return ''; }; @@ -161,7 +181,6 @@ const PromotionGeneralInformation = ({ setDiscountType(event.target.value); }} /> - {discountType === 'PERCENTAGE' && ( removeProduct(id)} + addedOptions={promotion?.products} /> )} {!isSubmitting && applyTo === 'CATEGORY' && ( removeCategory(id)} + addedOptions={promotion?.categories} /> )} {!isSubmitting && applyTo === 'BRAND' && ( removeBrand(id)} + addedOptions={promotion?.brands} /> )} diff --git a/backoffice/modules/promotion/models/Promotion.ts b/backoffice/modules/promotion/models/Promotion.ts index e3d6af61d0..b06a0960ab 100644 --- a/backoffice/modules/promotion/models/Promotion.ts +++ b/backoffice/modules/promotion/models/Promotion.ts @@ -16,8 +16,8 @@ export type PromotionDetail = { discountPercentage: number; discountAmount: number; isActive: boolean; - startDate: Date | string; - endDate: Date | string; + startDate: string; + endDate: string; brands: BrandVm[]; categories: CategoryGetVm[]; products: ProductVm[]; @@ -51,8 +51,8 @@ export type PromotionDto = { discountPercentage?: number; discountAmount?: number; isActive: boolean; - startDate: Date; - endDate: Date; + startDate: string; + endDate: string; brandIds: number[]; categoryIds: number[]; productIds: number[]; diff --git a/backoffice/modules/promotion/services/PromotionService.ts b/backoffice/modules/promotion/services/PromotionService.ts index 7f5585c3cc..9840a00152 100644 --- a/backoffice/modules/promotion/services/PromotionService.ts +++ b/backoffice/modules/promotion/services/PromotionService.ts @@ -9,13 +9,11 @@ export async function getPromotions(request: PromotionListRequest) { } export async function createPromotion(promotion: PromotionDto) { - const url = `${baseUrl}`; - return (await apiClientService.post(url, JSON.stringify(promotion))).json(); + return await apiClientService.post(baseUrl, JSON.stringify(promotion)); } export async function updatePromotion(promotion: PromotionDto) { - const url = `${baseUrl}/${promotion.id}`; - return (await apiClientService.put(url, promotion)).json(); + return await apiClientService.put(baseUrl, JSON.stringify(promotion)); } export async function getPromotion(id: number) { diff --git a/backoffice/pages/promotion/manager-promotion/[id]/edit.tsx b/backoffice/pages/promotion/manager-promotion/[id]/edit.tsx new file mode 100644 index 0000000000..4ad8b51ceb --- /dev/null +++ b/backoffice/pages/promotion/manager-promotion/[id]/edit.tsx @@ -0,0 +1,131 @@ +import { toastError } from '@commonServices/ToastService'; +import PromotionGeneralInformation from 'modules/promotion/components/PromotionGeneralInformation'; +import { PromotionDetail, PromotionDto } from 'modules/promotion/models/Promotion'; +import { getPromotion, updatePromotion } from 'modules/promotion/services/PromotionService'; +import { NextPage } from 'next'; +import { useRouter } from 'next/router'; +import { useEffect, useState } from 'react'; +import { useForm } from 'react-hook-form'; + +const PromotionUpdate: NextPage = () => { + const router = useRouter(); + const { id } = router.query; + + const { + register, + handleSubmit, + formState: { errors }, + setValue, + trigger, + } = useForm(); + + const [isSubmitting, setIsSubmitting] = useState(false); + + const [promotion, setPromotion] = useState(); + + useEffect(() => { + if (id) { + getPromotion(+id).then((data) => { + setPromotion(data); + setDefaultValues(data); + }); + } else { + toastError(`Promotion id ${id} not found`); + router.push({ pathname: `/404` }); //NOSONAR + } + }, []); + + const setDefaultValues = (promotion: PromotionDetail) => { + setValue('slug', promotion.slug); + setValue('couponCode', promotion.couponCode); + setValue('name', promotion.name); + setValue('applyTo', promotion.applyTo); + setValue('startDate', removeTime(promotion.startDate)); + setValue('endDate', removeTime(promotion.endDate)); + setValue('discountAmount', promotion.discountAmount); + setValue('discountPercentage', promotion.discountPercentage); + setValue('usageLimit', promotion.usageLimit); + setValue('usageType', promotion.usageType); + setValue('discountType', promotion.discountType); + setValue('description', promotion.description); + setValue('brandIds', promotion.brands?.map((brand) => brand.id) ?? []); + setValue('categoryIds', promotion.categories?.map((category) => category.id) ?? []); + setValue('productIds', promotion.products?.map((product) => product.id) ?? []); + setValue('isActive', promotion.isActive); + }; + + const removeTime = (date: string) => { + const DATE_PATTERN = /\d{4}-\d{2}-\d{2}/g; + return date.match(DATE_PATTERN)![0]; + }; + + const handleSubmitPromotion = async (event: PromotionDto) => { + let promotion: PromotionDto = { + id: +id!, + slug: event.slug, + couponCode: event.couponCode, + name: event.name, + applyTo: event.applyTo, + startDate: event.startDate, + endDate: event.endDate, + discountAmount: event.discountAmount ?? 0, + discountPercentage: event.discountPercentage ?? 0, + usageLimit: event.usageLimit, + usageType: event.usageType, + discountType: event.discountType, + description: event.description, + brandIds: event.brandIds, + categoryIds: event.categoryIds, + productIds: event.productIds, + isActive: event.isActive, + }; + + updatePromotion(promotion).then((response) => { + if (response.status === 200) { + router.replace('/promotion/manager-promotion'); + } + }); + }; + + const submitForm = () => { + setIsSubmitting(true); + handleSubmit(handleSubmitPromotion)(); + }; + + const cancel = () => { + window.location.href = '/promotion/manager-promotion'; + }; + + return ( +
+
+

Create Promotion

+
+ +
+ + +
+ +
+
+ ); +}; + +export default PromotionUpdate; diff --git a/backoffice/pages/promotion/manager-promotion/create.tsx b/backoffice/pages/promotion/manager-promotion/create.tsx index 2dc344305b..98150e07ea 100644 --- a/backoffice/pages/promotion/manager-promotion/create.tsx +++ b/backoffice/pages/promotion/manager-promotion/create.tsx @@ -2,10 +2,13 @@ import PromotionGeneralInformation from 'modules/promotion/components/PromotionG import { PromotionDto } from 'modules/promotion/models/Promotion'; import { createPromotion } from 'modules/promotion/services/PromotionService'; import { NextPage } from 'next'; +import { useRouter } from 'next/router'; import { useState } from 'react'; import { useForm } from 'react-hook-form'; const PromotionCreate: NextPage = () => { + const router = useRouter(); + const { register, handleSubmit, @@ -38,7 +41,7 @@ const PromotionCreate: NextPage = () => { createPromotion(promotion).then((response) => { if (response.status === 201) { - window.location.href = '/promotion/manager-promotion'; + router.replace('/promotion/manager-promotion'); } }); }; diff --git a/backoffice/pages/promotion/manager-promotion/index.tsx b/backoffice/pages/promotion/manager-promotion/index.tsx index 1976a86ae6..a307df706f 100644 --- a/backoffice/pages/promotion/manager-promotion/index.tsx +++ b/backoffice/pages/promotion/manager-promotion/index.tsx @@ -47,7 +47,10 @@ const PromotionList: NextPage = () => { date = new Date(date); } const month = date.getMonth() + 1; - return `${date.getFullYear()}-${month > 9 ? month : '0' + month}-${date.getDate()}`; + const dateNumber = date.getDate(); + return `${date.getFullYear()}-${month > 9 ? month : '0' + month}-${ + dateNumber > 9 ? dateNumber : '0' + dateNumber + }`; }; return ( @@ -118,7 +121,7 @@ const PromotionList: NextPage = () => { {convertToStringDate(promotion.startDate)} {convertToStringDate(promotion.endDate)} - +