diff --git a/src/api/menuCategory/index.ts b/src/api/menuCategory/index.ts index 37a14701..81fd64c1 100644 --- a/src/api/menuCategory/index.ts +++ b/src/api/menuCategory/index.ts @@ -1,9 +1,10 @@ import { get } from '@/lib/axios'; import { MajorCategory } from '@/type/menu/menuRequest'; +import { GetSearchSchoolRequest } from '@/type/menuCategory/menuCategoryRequest'; import { Result } from '@/type/response'; import { MENU_CAGEGORY_API } from '@/constants/_apiPath'; -const { MENU_CATEGORIES } = MENU_CAGEGORY_API; +const { MENU_CATEGORIES, SEARCH_SCHOOL } = MENU_CAGEGORY_API; const getMinorCategories = async (param: MajorCategory) => { const response = await get>(MENU_CATEGORIES, { @@ -14,6 +15,19 @@ const getMinorCategories = async (param: MajorCategory) => { return response.data; }; +/** + * @description 학교명 검색 api + */ +const getSearchSchool = async ({ keyword }: GetSearchSchoolRequest) => { + const response = await get>(SEARCH_SCHOOL, { + params: { + keyword, + }, + }); + return response.data; +}; + export const menuCategories = { getMinorCategories, + getSearchSchool, }; diff --git a/src/components/common/Calendar/index.tsx b/src/components/common/Calendar/index.tsx index 8c3656e1..063d976f 100644 --- a/src/components/common/Calendar/index.tsx +++ b/src/components/common/Calendar/index.tsx @@ -57,7 +57,7 @@ const Calendar = ({ date={date.format('D')} isHoliday={isHoliday(date)} isInvalid={isInvalidDate(date, year, month)} - data={data?.[formattedDate as keyof CalendarInfo]?.foods || []} + data={data?.[formattedDate]?.foods || []} isActive={isActive} index={index} totalDays={allDays.length} diff --git a/src/components/feature/AutoPlan/index.tsx b/src/components/feature/AutoPlan/index.tsx index 40a8dd7b..a65ca786 100644 --- a/src/components/feature/AutoPlan/index.tsx +++ b/src/components/feature/AutoPlan/index.tsx @@ -6,7 +6,7 @@ import { useQueryClient } from '@tanstack/react-query'; import { AxiosError } from 'axios'; import { useForm } from 'react-hook-form'; import { mealHeaderSchema } from '@/schema/mealSchema'; -import { CalendarInfo } from '@/type/mealType'; +import { CalendarInfo, MealHeaderForm } from '@/type/mealType'; import { MajorCategory } from '@/type/menu/menuRequest'; import { MenuResponse } from '@/type/menu/menuResponse'; import { @@ -21,10 +21,13 @@ import { transformCalendarToPostSave, transformResponseToCalendar, } from '@/utils/calendar'; +import { stringArraytoOptionArray } from '@/utils/meal'; import Button from '@/components/common/Button/Button'; +import Dropdown from '@/components/common/Dropdown'; import { Input } from '@/components/common/Input'; import MealForm from '@/components/common/MealForm'; -import { Selectbox } from '@/components/common/Selectbox'; +import OptionList from '@/components/common/OptionList'; +import { Option, Selectbox } from '@/components/common/Selectbox'; import { Caption1Grey500, H2BlackH2, @@ -33,14 +36,18 @@ import { import MealCalendar from '@/components/shared/Meal/MealCalender'; import { MealHeaderFormData } from '@/components/shared/Meal/MealHeader'; import { ORGANIZATION_LIST } from '@/constants/_category'; -import { AUTO_PLAN_BETA_MESSAGE } from '@/constants/_meal'; -import { MEAL_FORM_LEGEND } from '@/constants/_MealForm'; +import { AUTO_PLAN_BETA_MESSAGE, MAJOR_CATEGORIES } from '@/constants/_meal'; +import { + MEAL_FORM_LEGEND, + MINIMUM_SCHOOL_NAME_LENGTH, +} from '@/constants/_MealForm'; import { ROUTES } from '@/constants/_navbar'; import { PAGE_TITLE } from '@/constants/_pageTitle'; import { MEAL_HEADER_ERROR } from '@/constants/_schema'; import { usePostMonthMenusAuto } from '@/hooks/menu/usePostMonthMenusAuto'; import { usePostMonthMenusSave } from '@/hooks/menu/usePostMonthMenusSave'; import { useFetchMinorCategories } from '@/hooks/menuCategory/useFetchMinorCategories'; +import { useGetSearchSchool } from '@/hooks/menuCategory/useGetSearchSchool'; import { usePrefetchMinorCategories } from '@/hooks/menuCategory/usePrefetchMinorCategories'; import useNavigate from '@/hooks/useNavigate'; import { useToastStore } from '@/stores/useToastStore'; @@ -56,6 +63,9 @@ const AutoPlan = () => { minorCategory: '', }); const [isCategoryError, setIsCategoryError] = useState(false); + const [isOpen, setIsOpen] = useState(false); + const [options, setOptions] = useState([]); + const [keyword, setKeyword] = useState(''); const { year, month } = getCurrentYearMonthNow(); const showToast = useToastStore((state) => state.showToast); const { navigate } = useNavigate(); @@ -73,7 +83,10 @@ const AutoPlan = () => { register, handleSubmit, formState: { errors }, - } = useForm({ + watch, + getValues, + setValue, + } = useForm({ resolver: zodResolver(mealHeaderSchema), mode: 'onChange', }); @@ -173,6 +186,60 @@ const AutoPlan = () => { prefetchMinorCategories(); }, [hasCategories, prefetchMinorCategories]); + const handleSchoolNameSelect = (schoolName: string) => { + setValue('schoolName', schoolName); + setSelectedCategory((prev) => ({ + ...prev, + minorCategory: schoolName, + })); + setIsOpen(false); + }; + + const { + data: schoolNameData, + isSuccess: isSchoolNameSuccess, + isError: isSchoolNameError, + } = useGetSearchSchool( + { + keyword: keyword, + }, + { + enabled: keyword.length >= MINIMUM_SCHOOL_NAME_LENGTH, + }, + ); + + // 학교명 입력 후 검색 클릭 시 + const handleSearchClick = () => { + if (getValues('schoolName').length < MINIMUM_SCHOOL_NAME_LENGTH) + return null; + + setKeyword(getValues('schoolName')); + + if (isSchoolNameError) { + showToast( + '학교명 검색에 실패했습니다. 잠시 후 다시 시도해주세요.', + 'warning', + ); + setIsOpen(false); + return null; + } + }; + + useEffect(() => { + if (isSchoolNameSuccess) { + if (schoolNameData.data.length === 0) { + showToast('찾으시는 학교명이 없습니다.', 'warning'); + setIsOpen(false); + return; + } + const formattedOptions = stringArraytoOptionArray(schoolNameData.data); + setOptions(formattedOptions); + setIsOpen(true); + } + }, [isSchoolNameSuccess, schoolNameData]); + + const watchSchoolName = watch('schoolName'); + return (
{ selectedValue={selectedCategory.majorCategory} isError={isCategoryError} /> +
+ {selectedCategory.majorCategory === MAJOR_CATEGORIES[1] && ( +
+ + +
+ )} + + + +
+ {ORGANIZATION_LIST.map( (organization) => - selectedCategory.majorCategory === organization.value && ( + selectedCategory.majorCategory === organization.value && + selectedCategory.majorCategory !== MAJOR_CATEGORIES[1] && ( { - const [calendarData, setCalendarData] = useState({}); - const [selectedDate, setSelectedDate] = useState(''); - const [selectedCategory, setSelectedCategory] = useState({ - majorCategory: '', - minorCategory: '', - }); - const { year, month } = getCurrentYearMonthNow(); - const showToast = useToastStore((state) => state.showToast); - const { navigate } = useNavigate(); - const { setMonthMenuName, category } = useAutoPlanStore((state) => ({ - category: state.category, - setMonthMenuName: state.setMonthMenuName, - })); - - const queryClient = useQueryClient(); - const { mutate: postSaveMutate } = usePostMonthMenusSave(); - - const { - register, - handleSubmit, - getValues, - formState: { errors }, - } = useForm({ - resolver: zodResolver(mealHeaderSchema), - mode: 'onChange', - }); - - const handleDateClick = (date: string) => { - setSelectedDate(date); - }; - - const handleEditMenu = () => { - const inputData = getValues(); - setMonthMenuName(inputData.monthMenuName); - navigate(ROUTES.EDIT.AUTO); - }; - - const onSubmit = (data: MealHeaderFormData) => { - if (isAllFoodsEmpty(calendarData)) { - showToast('빈 식단은 생성할 수 없습니다.', 'warning', 3000); - return; - } - - const formattedData = transformCalendarToPostSave( - calendarData, - data.monthMenuName, - selectedCategory.majorCategory as MajorCategory, - selectedCategory.minorCategory, - ); - postSaveMutate(formattedData, { - onSuccess: ({ message }: Result) => { - showToast(message, 'success', 1000); - navigate(ROUTES.VIEW.PLAN); - }, - onError: (error: AxiosError) => { - const errorMessage = - error?.response?.data?.message || '자동 식단 저장 실패'; - showToast(errorMessage, 'warning', 1000); - }, - }); - }; - - const onError = () => { - if (errors.monthMenuName) { - showToast(MEAL_HEADER_ERROR.name.min, 'warning', 3000); - return; - } - }; - - useEffect(() => { - const menus = queryClient.getQueryData(['monthMenusAuto']); - if (!menus) return; - const calendarData = transformResponseToCalendar(year, month, menus); - setSelectedCategory({ - majorCategory: category.majorCategory, - minorCategory: category.minorCategory, - }); - setCalendarData(calendarData); - }, [ - year, - month, - queryClient, - category.majorCategory, - category.minorCategory, - ]); - - return ( - - - - - ); -}; - -export default AutoPlanCreate; diff --git a/src/components/feature/MealPlanEdit/index.tsx b/src/components/feature/MealPlanEdit/index.tsx index c56e5c52..9d3aeac2 100644 --- a/src/components/feature/MealPlanEdit/index.tsx +++ b/src/components/feature/MealPlanEdit/index.tsx @@ -6,7 +6,7 @@ import { useQueryClient } from '@tanstack/react-query'; import { AxiosError } from 'axios'; import { useForm } from 'react-hook-form'; import { mealHeaderSchema } from '@/schema/mealSchema'; -import { CalendarInfo } from '@/type/mealType'; +import { CalendarInfo, MealHeaderForm } from '@/type/mealType'; import { MajorCategory } from '@/type/menu/menuRequest'; import { FoodInfo, MenuResponseDTO } from '@/type/menu/menuResponse'; import { @@ -20,17 +20,33 @@ import { transformCalendarToPostSave, transformResponseToCalendar, } from '@/utils/calendar'; +import { stringArraytoOptionArray } from '@/utils/meal'; +import Button from '@/components/common/Button/Button'; +import Dropdown from '@/components/common/Dropdown'; +import { Input } from '@/components/common/Input'; import MealForm from '@/components/common/MealForm'; +import OptionList from '@/components/common/OptionList'; +import { Option, Selectbox } from '@/components/common/Selectbox'; +import { + H2BlackH2, + Subtitle2Green500, + Subtitle2Grey900, + Subtitle2White, +} from '@/components/common/Typography'; import MealCalendar from '@/components/shared/Meal/MealCalender'; -import MealHeader, { - MealHeaderFormData, -} from '@/components/shared/Meal/MealHeader'; -import { MEAL_FORM_LEGEND } from '@/constants/_MealForm'; +import { MealHeaderFormData } from '@/components/shared/Meal/MealHeader'; +import { ORGANIZATION_LIST } from '@/constants/_category'; +import { MAJOR_CATEGORIES } from '@/constants/_meal'; +import { + MEAL_FORM_LEGEND, + MINIMUM_SCHOOL_NAME_LENGTH, +} from '@/constants/_MealForm'; import { ROUTES } from '@/constants/_navbar'; import { PAGE_TITLE } from '@/constants/_pageTitle'; import { MEAL_HEADER_ERROR } from '@/constants/_schema'; import { usePutMonthMenus } from '@/hooks/menu/usePutMonthMenus'; import { useFetchMinorCategories } from '@/hooks/menuCategory/useFetchMinorCategories'; +import { useGetSearchSchool } from '@/hooks/menuCategory/useGetSearchSchool'; import useNavigate from '@/hooks/useNavigate'; import { useToastStore } from '@/stores/useToastStore'; @@ -38,6 +54,9 @@ type MealPlanEditProps = { id: string; }; +/** + * @description 식단 수정 페이지 + */ const MealPlanEdit = ({ id: monthMenuId }: MealPlanEditProps) => { const [cachedCalendarData, setCachedCalendarData] = useState( {}, @@ -51,8 +70,11 @@ const MealPlanEdit = ({ id: monthMenuId }: MealPlanEditProps) => { minorCategory: '', }); const [isCategoryError, setIsCategoryError] = useState(false); + const [isOpen, setIsOpen] = useState(false); + const [options, setOptions] = useState([]); + const [keyword, setKeyword] = useState(''); const showToast = useToastStore((state) => state.showToast); - const { navigate } = useNavigate(); + const { navigate, handleBack } = useNavigate(); const queryClient = useQueryClient(); const { minorCategories } = useFetchMinorCategories( @@ -65,11 +87,15 @@ const MealPlanEdit = ({ id: monthMenuId }: MealPlanEditProps) => { handleSubmit, formState: { errors }, reset, - } = useForm({ + watch, + getValues, + setValue, + } = useForm({ resolver: zodResolver(mealHeaderSchema), mode: 'onChange', defaultValues: { monthMenuName: '', + schoolName: '', }, }); @@ -179,6 +205,7 @@ const MealPlanEdit = ({ id: monthMenuId }: MealPlanEditProps) => { } = cachedMealPlanData.data; reset({ monthMenuName: monthMenuName, + schoolName: minorCategory, }); const { year, month } = getYearAndMonth(createAt); setYear(year); @@ -201,6 +228,60 @@ const MealPlanEdit = ({ id: monthMenuId }: MealPlanEditProps) => { getOriginalCalendar(); }, []); + const handleSchoolNameSelect = (schoolName: string) => { + setValue('schoolName', schoolName); + setSelectedCategory((prev) => ({ + ...prev, + minorCategory: schoolName, + })); + setIsOpen(false); + }; + + const { + data: schoolNameData, + isSuccess: isSchoolNameSuccess, + isError: isSchoolNameError, + } = useGetSearchSchool( + { + keyword: keyword, + }, + { + enabled: keyword.length >= MINIMUM_SCHOOL_NAME_LENGTH, + }, + ); + + // 학교명 입력 후 검색 클릭 시 + const handleSearchClick = () => { + if (getValues('schoolName').length < MINIMUM_SCHOOL_NAME_LENGTH) + return null; + + setKeyword(getValues('schoolName')); + + if (isSchoolNameError) { + showToast( + '학교명 검색에 실패했습니다. 잠시 후 다시 시도해주세요.', + 'warning', + ); + setIsOpen(false); + return null; + } + }; + + useEffect(() => { + if (isSchoolNameSuccess) { + if (schoolNameData.data.length === 0) { + showToast('찾으시는 학교명이 없습니다.', 'warning'); + setIsOpen(false); + return; + } + const formattedOptions = stringArraytoOptionArray(schoolNameData.data); + setOptions(formattedOptions); + setIsOpen(true); + } + }, [isSchoolNameSuccess, schoolNameData]); + + const watchSchoolName = watch('schoolName'); + if (!calendarData) { return
로딩 중...
; } @@ -210,16 +291,99 @@ const MealPlanEdit = ({ id: monthMenuId }: MealPlanEditProps) => { legend={MEAL_FORM_LEGEND.mealPlan.edit} handleSubmit={handleSubmit(onSubmit, onError)} > - +
+
+ {PAGE_TITLE.mealPlan.edit} +
+
+ {register && errors && ( +
+ +
+ )} + +
+ { + handleChangeCategory('majorCategory', majorCategory); + }} + selectedValue={selectedCategory.majorCategory} + isError={isCategoryError} + /> +
+ {selectedCategory.majorCategory === MAJOR_CATEGORIES[1] && ( +
+ + +
+ )} + + + +
+ {ORGANIZATION_LIST.map( + (organization) => + selectedCategory.majorCategory === organization.value && + selectedCategory.majorCategory !== MAJOR_CATEGORIES[1] && ( + + handleChangeCategory('minorCategory', minorCategory) + } + selectedValue={selectedCategory.minorCategory} + isError={isCategoryError} + /> + ), + )} +
+ +
+
+ + +
+ +
+
+
{ majorCategory: '', minorCategory: '', }); - const { year, month } = getCurrentYearMonthNow(); const [isCategoryError, setIsCategoryError] = useState(false); + const [isOpen, setIsOpen] = useState(false); + const [options, setOptions] = useState([]); + const [keyword, setKeyword] = useState(''); + const { year, month } = getCurrentYearMonthNow(); const showToast = useToastStore((state) => state.showToast); + const { navigate } = useNavigate(); const { setMonthMenuName, setCategory, setCalendar } = useMenualPlanStore( (state) => ({ setMonthMenuName: state.setMonthMenuName, @@ -48,7 +63,6 @@ const MenualPlan = () => { setCalendar: state.setCalendar, }), ); - const { navigate } = useNavigate(); const { minorCategories } = useFetchMinorCategories( selectedCategory.majorCategory, @@ -60,7 +74,10 @@ const MenualPlan = () => { register, handleSubmit, formState: { errors }, - } = useForm({ + watch, + getValues, + setValue, + } = useForm({ resolver: zodResolver(mealHeaderSchema), mode: 'onChange', }); @@ -90,10 +107,13 @@ const MenualPlan = () => { if (isValidDateString(date)) setSelectedDate(date); }; - const handleResetMenu = () => { - setCalendarData({}); - setSelectedDate(''); - }; + const isBothSelected = + selectedCategory.majorCategory && selectedCategory.minorCategory; + + // const handleResetMenu = () => { + // setCalendarData({}); + // setSelectedDate(''); + // }; const onSubmit = (data: MealHeaderFormData) => { const { majorCategory, minorCategory } = selectedCategory; @@ -129,22 +149,157 @@ const MenualPlan = () => { prefetchMinorCategories(); }, [hasCategories, prefetchMinorCategories]); + const handleSchoolNameSelect = (schoolName: string) => { + setValue('schoolName', schoolName); + setSelectedCategory((prev) => ({ + ...prev, + minorCategory: schoolName, + })); + setIsOpen(false); + }; + + const { + data: schoolNameData, + isSuccess: isSchoolNameSuccess, + isError: isSchoolNameError, + } = useGetSearchSchool( + { + keyword: keyword, + }, + { + enabled: keyword.length >= MINIMUM_SCHOOL_NAME_LENGTH, + }, + ); + + // 학교명 입력 후 검색 클릭 시 + const handleSearchClick = () => { + if (getValues('schoolName').length < MINIMUM_SCHOOL_NAME_LENGTH) + return null; + + setKeyword(getValues('schoolName')); + + if (isSchoolNameError) { + showToast( + '학교명 검색에 실패했습니다. 잠시 후 다시 시도해주세요.', + 'warning', + ); + setIsOpen(false); + return null; + } + }; + + useEffect(() => { + if (isSchoolNameSuccess) { + if (schoolNameData.data.length === 0) { + showToast('찾으시는 학교명이 없습니다.', 'warning'); + setIsOpen(false); + return; + } + const formattedOptions = stringArraytoOptionArray(schoolNameData.data); + setOptions(formattedOptions); + setIsOpen(true); + } + }, [isSchoolNameSuccess, schoolNameData]); + + const watchSchoolName = watch('schoolName'); + return (
- +
+
+ {PAGE_TITLE.menualPlan.default} +
+
+ {register && errors && ( +
+ +
+ )} + +
+ { + handleChangeCategory('majorCategory', majorCategory); + }} + selectedValue={selectedCategory.majorCategory} + isError={isCategoryError} + /> + +
+ {selectedCategory.majorCategory === MAJOR_CATEGORIES[1] && ( +
+ + +
+ )} + + + +
+ + {ORGANIZATION_LIST.map( + (item) => + selectedCategory.majorCategory === item.value && + selectedCategory.majorCategory !== MAJOR_CATEGORIES[1] && ( + + handleChangeCategory('minorCategory', minorCategory) + } + selectedValue={selectedCategory.minorCategory} + isError={isCategoryError} + /> + ), + )} +
+ + +
+
+ { useState(category); const { year, month } = getCurrentYearMonthNow(); const [isCategoryError, setIsCategoryError] = useState(false); + const [isOpen, setIsOpen] = useState(false); + const [options, setOptions] = useState([]); + const [keyword, setKeyword] = useState(''); const showToast = useToastStore((state) => state.showToast); const { navigate } = useNavigate(); + const isBothSelected = + selectedCategory.majorCategory && selectedCategory.minorCategory; + const { minorCategories } = useFetchMinorCategories( selectedCategory.majorCategory, ); @@ -57,11 +74,15 @@ const MenualPlanEdit = () => { register, handleSubmit, formState: { errors }, - } = useForm({ + watch, + getValues, + setValue, + } = useForm({ resolver: zodResolver(mealHeaderSchema), mode: 'onChange', defaultValues: { monthMenuName, + schoolName: category.minorCategory, }, }); @@ -140,20 +161,154 @@ const MenualPlanEdit = () => { } }; + const handleSchoolNameSelect = (schoolName: string) => { + setValue('schoolName', schoolName); + setSelectedCategory((prev) => ({ + ...prev, + minorCategory: schoolName, + })); + setIsOpen(false); + }; + + const { + data: schoolNameData, + isSuccess: isSchoolNameSuccess, + isError: isSchoolNameError, + } = useGetSearchSchool( + { + keyword: keyword, + }, + { + enabled: keyword.length >= MINIMUM_SCHOOL_NAME_LENGTH, + }, + ); + + // 학교명 입력 후 검색 클릭 시 + const handleSearchClick = () => { + if (getValues('schoolName').length < MINIMUM_SCHOOL_NAME_LENGTH) + return null; + + setKeyword(getValues('schoolName')); + + if (isSchoolNameError) { + showToast( + '학교명 검색에 실패했습니다. 잠시 후 다시 시도해주세요.', + 'warning', + ); + setIsOpen(false); + return null; + } + }; + + useEffect(() => { + if (isSchoolNameSuccess) { + if (schoolNameData.data.length === 0) { + showToast('찾으시는 학교명이 없습니다.', 'warning'); + setIsOpen(false); + return; + } + const formattedOptions = stringArraytoOptionArray(schoolNameData.data); + setOptions(formattedOptions); + setIsOpen(true); + } + }, [isSchoolNameSuccess, schoolNameData]); + + const watchSchoolName = watch('schoolName'); + return ( - +
+
+ {PAGE_TITLE.menualPlan.edit} +
+
+ {register && errors && ( +
+ +
+ )} + +
+ { + handleChangeCategory('majorCategory', majorCategory); + }} + selectedValue={selectedCategory.majorCategory} + isError={isCategoryError} + /> +
+ {selectedCategory.majorCategory === MAJOR_CATEGORIES[1] && ( +
+ + +
+ )} + + + +
+ + {ORGANIZATION_LIST.map( + (organization) => + selectedCategory.majorCategory === organization.value && + selectedCategory.majorCategory !== MAJOR_CATEGORIES[1] && ( + + handleChangeCategory('minorCategory', minorCategory) + } + selectedValue={selectedCategory.minorCategory} + isError={isCategoryError} + /> + ), + )} +
+ + +
+
+ [...menuCategoryKeys.all, request?.keyword] as const, +}; diff --git a/src/hooks/menuCategory/useGetSearchSchool.ts b/src/hooks/menuCategory/useGetSearchSchool.ts new file mode 100644 index 00000000..4dd57371 --- /dev/null +++ b/src/hooks/menuCategory/useGetSearchSchool.ts @@ -0,0 +1,17 @@ +import { useQuery } from '@tanstack/react-query'; +import { menuCategories } from '@/api/menuCategory'; +import { GetSearchSchoolRequest } from '@/type/menuCategory/menuCategoryRequest'; +import { menuCategoryKeys } from '@/hooks/menuCategory/queryKey'; + +export const useGetSearchSchool = ( + request: GetSearchSchoolRequest, + options?: { + enabled?: boolean; + }, +) => { + return useQuery({ + queryKey: menuCategoryKeys.searchSchool(request), + queryFn: () => menuCategories.getSearchSchool(request), + ...options, + }); +}; diff --git a/src/type/mealType.ts b/src/type/mealType.ts index 0cdcf24d..a12382ac 100644 --- a/src/type/mealType.ts +++ b/src/type/mealType.ts @@ -6,3 +6,8 @@ export type CalendarInfo = { foods: FoodInfo[]; }; }; + +export type MealHeaderForm = { + monthMenuName: string; + schoolName: string; +}; diff --git a/src/type/menuCategory/menuCategoryRequest.ts b/src/type/menuCategory/menuCategoryRequest.ts new file mode 100644 index 00000000..8ed5095d --- /dev/null +++ b/src/type/menuCategory/menuCategoryRequest.ts @@ -0,0 +1,3 @@ +export type GetSearchSchoolRequest = { + keyword: string; +}; diff --git a/src/utils/calendar.ts b/src/utils/calendar.ts index 9ff58a04..84768789 100644 --- a/src/utils/calendar.ts +++ b/src/utils/calendar.ts @@ -93,7 +93,6 @@ export const transformResponseToCalendar = ( apiData.forEach((menu, index) => { const currentDate = startOfMonth.add(index, 'day'); - if (currentDate.month() !== month - 1) return; const formattedDate = formatFullDate(currentDate); @@ -113,12 +112,18 @@ export const transformResponseToCalendar = ( fat: food.fat, })); - if (filteredFoods.length > 0) { + const menuDate = (menu as MonthMenu).menuDate; + + if (filteredFoods.length === 0) return null; + + if (type === 'auto') { calendarData[formattedDate] = { - menuId: - type === 'auto' - ? (menu as MenuResponse).menuId - : (menu as MonthMenu).menuId, + menuId: (menu as MenuResponse).menuId, + foods: filteredFoods, + }; + } else { + calendarData[menuDate] = { + menuId: (menu as MonthMenu).menuId, foods: filteredFoods, }; } diff --git a/src/utils/meal.ts b/src/utils/meal.ts index df127ce0..21f31a9f 100644 --- a/src/utils/meal.ts +++ b/src/utils/meal.ts @@ -1,10 +1,10 @@ +import { Option } from '@/components/common/Selectbox'; + /** * @description 소수점이 전부 0인 숫자들 정수로 변환 (메뉴 영양 정보 값) * @example 84.000 -> 84 - * @param value - * @returns */ -export function removeTrailingZeros(value: number): number { +export const removeTrailingZeros = (value: number): number => { const stringValue = typeof value === 'number' ? value.toString() : value; if (stringValue.includes('.')) { @@ -15,4 +15,14 @@ export function removeTrailingZeros(value: number): number { } return Number(stringValue); -} +}; + +/** + * @description api response로 받은 string 배열을 selectbox options 타입으로 변환 + * @example ['A학교', 'B학교'] -> [{value: 'A학교', label: 'A학교'} , {value: 'B학교', label: 'B학교'}] + */ +export const stringArraytoOptionArray = (items: string[]): Option[] => + items.map((item) => ({ + value: item, + label: item, + }));