Skip to content

Commit 3e910d2

Browse files
authored
Merge pull request #61 from wafflestudio/seoyeon
Seoyeon
2 parents 3a017eb + 1da436e commit 3e910d2

38 files changed

Lines changed: 2277 additions & 1154 deletions

public/assets/bottom_calendar.svg

Lines changed: 13 additions & 0 deletions
Loading

public/assets/bottom_profile.svg

Lines changed: 10 additions & 0 deletions
Loading

public/assets/bottom_reviews.svg

Lines changed: 7 additions & 0 deletions
Loading

public/assets/bottom_timetable.svg

Lines changed: 6 additions & 0 deletions
Loading

public/assets/filter.svg

Lines changed: 11 additions & 0 deletions
Loading

src/contexts/EventContext.tsx

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,17 @@ import React, {
33
type ReactNode,
44
useCallback,
55
useContext,
6-
useEffect,
76
useState,
87
} from "react";
98
import {
10-
getCategoryGroups,
119
getDayEvents,
1210
getEventDetail,
1311
getEventSearch,
1412
getMonthEvents,
15-
getOrganizations,
1613
} from "@api/event";
1714
import { formatDateToYYYYMMDD } from "@calendarUtil/dateFormatter";
1815
import { getMonthRange } from "@calendarUtil/getMonthRange";
1916
import type {
20-
Category,
21-
CategoryGroupWithCategories,
2217
DayViewParams,
2318
Event,
2419
EventDetail,
@@ -39,14 +34,10 @@ interface EventContextType {
3934
setDayDate: React.Dispatch<React.SetStateAction<Date>>;
4035
searchResults: SearchResult | null;
4136

42-
categoryGroups: CategoryGroupWithCategories[];
43-
organizations: Category[];
44-
4537
isLoadingMonth: boolean;
4638
isLoadingWeek: boolean;
4739
isLoadingDay: boolean;
4840
isLoadingSearch: boolean;
49-
isLoadingMeta: boolean;
5041
isLoadingDetail: boolean;
5142

5243
calendarError: string | null;
@@ -61,7 +52,6 @@ interface EventContextType {
6152
clearSearch: () => void;
6253

6354
fetchEventById: (id: number) => Promise<EventDetail | null>;
64-
refreshMetadata: () => Promise<void>;
6555
}
6656
const EventContext = createContext<EventContextType | undefined>(undefined);
6757

@@ -78,44 +68,16 @@ export const EventProvider: React.FC<{ children: ReactNode }> = ({
7868
const [dayViewEvents, setDayViewEvents] = useState<Event[]>([]);
7969
const [searchResults, setSearchResults] = useState<SearchResult | null>(null);
8070

81-
const [categoryGroups, setCategoryGroups] = useState<
82-
CategoryGroupWithCategories[]
83-
>([]);
84-
const [organizations, setOrganizations] = useState<Category[]>([]);
85-
8671
const [isLoadingMonth, setIsLoadingMonth] = useState(false);
8772
const [isLoadingWeek, setIsLoadingWeek] = useState(false);
8873
const [isLoadingDay, setIsLoadingDay] = useState(false);
8974
const [isLoadingSearch, setIsLoadingSearch] = useState(false);
9075
const [isLoadingDetail, setIsLoadingDetail] = useState(false);
91-
const [isLoadingMeta, setIsLoadingMeta] = useState(false);
9276

9377
const [calendarError, setCalendarError] = useState<string | null>(null);
9478
const [detailError, setDetailError] = useState<string | null>(null);
9579
const [searchError, setSearchError] = useState<string | null>(null);
9680

97-
// Fetch category & organizations (metadata)
98-
const refreshMetadata = useCallback(async () => {
99-
setIsLoadingMeta(true);
100-
try {
101-
const [groupsData, orgsData] = await Promise.all([
102-
getCategoryGroups(),
103-
getOrganizations(),
104-
]);
105-
setCategoryGroups(groupsData);
106-
setOrganizations(orgsData);
107-
} catch (err) {
108-
console.error("Failed to load metadata", err);
109-
setCalendarError("Failed to load categories.");
110-
} finally {
111-
setIsLoadingMeta(false);
112-
}
113-
}, []);
114-
115-
// metadata initial load
116-
useEffect(() => {
117-
refreshMetadata();
118-
}, [refreshMetadata]);
11981

12082
/* ACTIONS */
12183
const fetchMonthEvents = useCallback(
@@ -260,14 +222,11 @@ export const EventProvider: React.FC<{ children: ReactNode }> = ({
260222
setDayDate,
261223

262224
searchResults,
263-
categoryGroups,
264-
organizations,
265225

266226
isLoadingMonth,
267227
isLoadingWeek,
268228
isLoadingDay,
269229
isLoadingSearch,
270-
isLoadingMeta,
271230
isLoadingDetail,
272231

273232
calendarError,
@@ -281,7 +240,6 @@ export const EventProvider: React.FC<{ children: ReactNode }> = ({
281240
searchEvents,
282241
clearSearch,
283242
fetchEventById,
284-
refreshMetadata,
285243
};
286244

287245
return (

src/contexts/FilterContext.tsx

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,32 @@ import {
33
type Dispatch,
44
type ReactNode,
55
type SetStateAction,
6+
useCallback,
67
useContext,
8+
useEffect,
79
useState,
810
} from "react";
9-
import type { Category } from "@types";
11+
import { getCategoryGroups, getOrganizations } from "@api/event";
12+
import type { Category, CategoryGroupWithCategories } from "@types";
1013

1114
interface FilterContextType {
15+
filterSheetShowing: boolean;
16+
setFilterSheetShowing: (value: boolean) => void;
17+
18+
categoryGroups: CategoryGroupWithCategories[];
19+
organizations: Category[];
20+
refreshMetadata: () => Promise<void>;
21+
isLoadingMeta: boolean;
22+
1223
globalStatus: Category[];
1324
globalOrg: Category[];
1425
globalCategory: Category[];
1526

1627
setGlobalStatus: Dispatch<SetStateAction<Category[]>>;
1728
setGlobalOrg: Dispatch<SetStateAction<Category[]>>;
1829
setGlobalCategory: Dispatch<SetStateAction<Category[]>>;
30+
31+
filterError: string | null;
1932
}
2033

2134
const FilterContext = createContext<FilterContextType | undefined>(undefined);
@@ -25,19 +38,68 @@ export const FilterContextProvider = ({
2538
}: {
2639
children: ReactNode;
2740
}) => {
28-
const [globalStatus, setGlobalStatus] = useState<Category[]>([]);
41+
const [categoryGroups, setCategoryGroups] = useState<
42+
CategoryGroupWithCategories[]
43+
>([]);
44+
// 모집중
45+
const isApplying: Category =
46+
categoryGroups.find((g) => g.group.id===1)?.categories.find(c => c.id === 1)
47+
|| {
48+
"id": 1,
49+
"groupId": 1,
50+
"name": "모집중",
51+
"sortOrder": 1
52+
};
53+
const [organizations, setOrganizations] = useState<Category[]>([]);
54+
const [isLoadingMeta, setIsLoadingMeta] = useState(false);
55+
56+
const [globalStatus, setGlobalStatus] = useState<Category[]>([isApplying]);
2957
const [globalOrg, setGlobalOrg] = useState<Category[]>([]);
3058
const [globalCategory, setGlobalCategory] = useState<Category[]>([]);
3159

60+
const [filterSheetShowing, setFilterSheetShowing] = useState<boolean>(false);
61+
const [filterError, setFilterError] = useState<string | null>(null);
62+
63+
// Fetch category & organizations (metadata)
64+
const refreshMetadata = useCallback(async () => {
65+
setIsLoadingMeta(true);
66+
try {
67+
const [groupsData, orgsData] = await Promise.all([
68+
getCategoryGroups(),
69+
getOrganizations(),
70+
]);
71+
setCategoryGroups(groupsData);
72+
setOrganizations(orgsData);
73+
} catch (err) {
74+
console.error("Failed to load metadata", err);
75+
setFilterError("Failed to load categories.");
76+
} finally {
77+
setIsLoadingMeta(false);
78+
}
79+
}, []);
80+
81+
// metadata initial load
82+
useEffect(() => {
83+
refreshMetadata();
84+
}, [refreshMetadata]);
85+
86+
3287
return (
3388
<FilterContext.Provider
3489
value={{
90+
filterSheetShowing,
91+
setFilterSheetShowing,
92+
categoryGroups,
93+
organizations,
94+
isLoadingMeta,
95+
refreshMetadata,
3596
globalStatus,
3697
globalOrg,
3798
globalCategory,
3899
setGlobalStatus,
39100
setGlobalOrg,
40101
setGlobalCategory,
102+
filterError
41103
}}
42104
>
43105
{children}

src/contexts/UserDataContext.tsx

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface UserDataContextType {
1616
excludedKeywords: { id: number; keyword: string }[];
1717
eventMemos: Memo[];
1818
refreshUserData: () => void;
19+
// fetchInterestCategories: () => void;
1920
addExcludedKeyword: (keyword: string) => Promise<void>;
2021
deleteExcludedKeyword: (id: number) => Promise<void>;
2122
toggleBookmark: (event: Event) => Promise<void>;
@@ -79,29 +80,32 @@ export const UserDataProvider = ({ children }: { children: ReactNode }) => {
7980
}
8081
}, [isAuthenticated, fetchAll]);
8182

82-
// Optimistic UI Update for Bookmarking
83-
const toggleBookmark = async (event: Event) => {
84-
const isBookmarked = bookmarkedEvents.some((b) => b.id === event.id);
85-
86-
// 1. Optimistic Update
87-
if (isBookmarked) {
88-
setBookmarkedEvents((prev) => prev.filter((b) => b.id !== event.id));
89-
} else {
90-
setBookmarkedEvents((prev) => [...prev, event]);
83+
// get interestCategories & update
84+
/*
85+
const fetchInterestCategories = async () => {
86+
try {
87+
const newInterestCategories = await userService.getInterestCategories();
88+
setInterestCategories(newInterestCategories);
89+
} catch (e) {
90+
console.error("error in fetching interest categories", e);
9191
}
92+
}
93+
*/
9294

93-
// 2. API Call
95+
const toggleBookmark = async (event: Event) => {
96+
const isBookmarked = bookmarkedEvents.some((b) => b.id === event.id);
9497
try {
9598
if (isBookmarked) {
9699
await userService.removeBookmark(event.id);
97100
} else {
98101
await userService.addBookmark(event.id);
99102
}
103+
104+
const newBookmarks = await userService.getBookmarks(1);
105+
setBookmarkedEvents(newBookmarks);
106+
100107
} catch (error) {
101-
// Revert on failure
102-
fetchAll();
103108
console.error(error);
104-
alert("Failed to update bookmark");
105109
}
106110
};
107111

@@ -185,6 +189,7 @@ export const UserDataProvider = ({ children }: { children: ReactNode }) => {
185189
interestCategories,
186190
eventMemos,
187191
refreshUserData: fetchAll,
192+
// fetchInterestCategories,
188193
toggleBookmark,
189194
getMemoByTag,
190195
addMemo,

src/pages/CalendarView.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { useEvents } from "@contexts/EventContext";
1717
import { useFilter } from "@contexts/FilterContext";
1818
import { formatDateToYYYYMMDD } from "@calendarUtil/dateFormatter";
1919
import { useUserData } from "@/contexts/UserDataContext";
20+
import BottomNav from "@/widgets/BottomNav";
21+
import { FilterSheet } from "@/widgets/FilterSheet/FilterSheet";
2022

2123
const CalendarView = () => {
2224
// EventContext
@@ -73,8 +75,7 @@ const CalendarView = () => {
7375
const paramMonth: FetchMonthEventArgs = {
7476
start: currentDate,
7577
};
76-
if (globalCategory)
77-
paramMonth.eventTypeId = globalCategory.map((g) => g.id);
78+
if (globalCategory) paramMonth.eventTypeId = globalCategory.map((g) => g.id);
7879
if (globalOrg) paramMonth.orgId = globalOrg.map((g) => g.id);
7980
if (globalStatus) paramMonth.statusId = globalStatus.map((g) => g.id);
8081

@@ -184,9 +185,7 @@ const CalendarView = () => {
184185

185186
return (
186187
<div className={styles.container}>
187-
<div className={styles.sidebarContainer}>
188-
<Sidebar />
189-
</div>
188+
<Sidebar />
190189
<div className={styles.calendarContainer}>
191190
<div className={styles.calendarWrapper}>
192191
<MyCalendar
@@ -212,6 +211,8 @@ const CalendarView = () => {
212211
</div>
213212
)}
214213
</div>
214+
<FilterSheet />
215+
<BottomNav />
215216
</div>
216217
);
217218
};

0 commit comments

Comments
 (0)