Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9d1c84c
chore: autoplancreate 컴포넌트 삭제
grapefruit13 Mar 25, 2025
48f7264
feat: 학교명 검색 api endpoint 추가
grapefruit13 Mar 25, 2025
f17edee
feat: 학교명 검색 쿼리키 추가
grapefruit13 Mar 25, 2025
6cf72a0
feat: 학교명 검색 api 함수 구현
grapefruit13 Mar 25, 2025
9d88972
feat: 학교명 검색 api 리퀘스트 타입 정의
grapefruit13 Mar 25, 2025
fb2b091
feat: 학교명 검색 훅 구현
grapefruit13 Mar 25, 2025
6414d6f
temp: todo 주석 표시
grapefruit13 Mar 25, 2025
2f54cde
fix: search school api path 수정
grapefruit13 Apr 5, 2025
999d64d
fix: 학교명 검색 api response 타입 및 경로 수정
grapefruit13 Apr 5, 2025
5b1b593
feat: category mappings 에서 학교명 옵션 주석 처리
grapefruit13 Apr 5, 2025
b0b225a
feat: 최소 학교명 검색 길이 상수 정의
grapefruit13 Apr 5, 2025
39172f2
feat: string array to option array 유틸 함수 구현 및 주석 추가
grapefruit13 Apr 5, 2025
dbe3397
feat: meal header form 타입 정의
grapefruit13 Apr 5, 2025
876e0f4
fix: 학교명 검색 use 훅에 options 추가
grapefruit13 Apr 5, 2025
d4df8f2
feat: 자동식단 페이지 - 학교명 검색 api 바인딩
grapefruit13 Apr 5, 2025
be54e56
feat: 식단 수정 페이지 - meal header 사용 해제, 학교명 검색 api 바인딩
grapefruit13 Apr 5, 2025
9945b49
feat: 수동 식단 페이지 - meal header 사용 해제, 학교명 검색 api 바인딩
grapefruit13 Apr 5, 2025
7c6bcd6
fix: 자동식단 페이지 - 상수 변수 적용
grapefruit13 Apr 5, 2025
34947d0
feat: 수동 식단 수정 페이지 - 학교명 검색 api 바인딩
grapefruit13 Apr 5, 2025
75c5010
fix: 자동식단, 수동식단수정, 수동식단페이지 - 스타일 수정
grapefruit13 Apr 5, 2025
abec28d
fix: transformResponseToCalender 유틸 함수 수정
grapefruit13 Apr 6, 2025
97f7348
fix: Calendar 컴포넌트 data 프롭 수정
grapefruit13 Apr 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/api/menuCategory/index.ts
Original file line number Diff line number Diff line change
@@ -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<Result<string[] | null>>(MENU_CATEGORIES, {
Expand All @@ -14,6 +15,19 @@ const getMinorCategories = async (param: MajorCategory) => {
return response.data;
};

/**
* @description 학교명 검색 api
*/
const getSearchSchool = async ({ keyword }: GetSearchSchoolRequest) => {
const response = await get<Result<string[] | []>>(SEARCH_SCHOOL, {
params: {
keyword,
},
});
return response.data;
};

export const menuCategories = {
getMinorCategories,
getSearchSchool,
};
2 changes: 1 addition & 1 deletion src/components/common/Calendar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
110 changes: 104 additions & 6 deletions src/components/feature/AutoPlan/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand All @@ -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';
Expand All @@ -56,6 +63,9 @@ const AutoPlan = () => {
minorCategory: '',
});
const [isCategoryError, setIsCategoryError] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const [options, setOptions] = useState<Option[]>([]);
const [keyword, setKeyword] = useState('');
const { year, month } = getCurrentYearMonthNow();
const showToast = useToastStore((state) => state.showToast);
const { navigate } = useNavigate();
Expand All @@ -73,7 +83,10 @@ const AutoPlan = () => {
register,
handleSubmit,
formState: { errors },
} = useForm<MealHeaderFormData>({
watch,
getValues,
setValue,
} = useForm<MealHeaderForm>({
resolver: zodResolver(mealHeaderSchema),
mode: 'onChange',
});
Expand Down Expand Up @@ -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 (
<div className='flex gap-6'>
<MealForm
Expand Down Expand Up @@ -211,9 +278,40 @@ const AutoPlan = () => {
selectedValue={selectedCategory.majorCategory}
isError={isCategoryError}
/>
<div className='relative'>
{selectedCategory.majorCategory === MAJOR_CATEGORIES[1] && (
<div className='flex gap-4'>
<Input
variant='white'
size='s'
className='h-12'
placeholder='두 글자 이상 입력'
autoComplete='off'
{...register('schoolName')}
/>
<Button
variant='teritary'
className='min-w-[68px]'
disabled={watchSchoolName?.length < 2}
onClick={handleSearchClick}
>
<Subtitle2White>검색</Subtitle2White>
</Button>
</div>
)}
<Dropdown isOpen={isOpen} className='top-12'>
<OptionList
options={options}
onSelect={handleSchoolNameSelect}
size='basic'
/>
</Dropdown>
</div>

{ORGANIZATION_LIST.map(
(organization) =>
selectedCategory.majorCategory === organization.value && (
selectedCategory.majorCategory === organization.value &&
selectedCategory.majorCategory !== MAJOR_CATEGORIES[1] && (
<Selectbox
key={organization.value}
options={minorCategories}
Expand Down
146 changes: 0 additions & 146 deletions src/components/feature/AutoPlanCreate/index.tsx

This file was deleted.

Loading