Skip to content

Commit dadf1f6

Browse files
committed
api 연결
1 parent 2e8d4e5 commit dadf1f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1155
-1690
lines changed

app/(tabs)/Home.tsx

+6-704
Large diffs are not rendered by default.

app/(tabs)/Settings.tsx

+42-24
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,75 @@ import SwitchOffIcon from "@/assets/images/icon/Switch/Switch-Off.svg";
99
import { createNativeStackNavigator } from "@react-navigation/native-stack";
1010
import Keyword from "../../app/Setting/Keyword";
1111
import RegisKeyword from "../../app/Setting/RegisKeyword";
12-
import AsyncStorage from "@react-native-async-storage/async-storage";
12+
// import AsyncStorage from "@react-native-async-storage/async-storage";
1313
import KeywordBox from "@/components/setting/KeywordBox";
1414
import Error from "../Setting/Error";
1515
import { getFocusedRouteNameFromRoute } from "@react-navigation/native";
16+
import { getKeywords } from "@/service/keyword/getKeywords";
17+
import { toggleAlarmStatus } from "@/service/alarm/toggleAlarmStatus";
18+
import { getAlarmStatus } from "@/service/alarm/getAlarmStatus";
19+
import { getMinimumVersion } from "@/service/update/getMinimumVersion";
1620

1721
export function Settings({ navigation }: { navigation: any }) {
1822
const [keywords, setKeywords] = useState<string[]>([]);
1923
const [isNotificationEnabled, setIsNotificationEnabled] =
2024
useState<boolean>(false);
2125
const [isLatestVersion, setIsLatestVersion] = useState<boolean>(true); // 최신 버전 여부 상태
22-
const currentVersion = "1.0.0"; // 현재 앱 버전
23-
const latestVersion = "1.1.0"; // 최신 버전, 서버에서 가져온다고 가정
24-
25-
// useEffect(() => {
26-
// // 버전 체크 로직 (여기서는 최신 버전이 아닌 경우를 가정)
27-
// if (currentVersion !== latestVersion) {
28-
// setIsLatestVersion(false);
29-
// }
26+
const [latestVersion, setLatestVersion] = useState<string>("1.1.0"); // 최신 버전 상태
3027

31-
// loadKeywords();
32-
// }, []);
28+
const currentVersion = "1.0.0"; // 현재 앱 버전
3329

3430
const loadKeywords = async () => {
3531
try {
36-
const storedKeywords = await AsyncStorage.getItem("keywords");
37-
const keywordsArray = storedKeywords ? JSON.parse(storedKeywords) : [];
38-
setKeywords(keywordsArray);
32+
const keywordList = await getKeywords(); // API 호출
33+
const extractedKeywords = keywordList.map(
34+
(item: { keyword: string }) => item.keyword
35+
);
36+
setKeywords(extractedKeywords); // 키워드 상태 업데이트
3937
} catch (error) {
4038
console.error("키워드 불러오기 오류:", error);
4139
}
4240
};
43-
const version = "1.0.0";
44-
// 알림 설정 상태 변경 시 AsyncStorage에 저장
41+
42+
const loadNotificationStatus = async () => {
43+
try {
44+
const alarmStatus = await getAlarmStatus(); // 작성한 getAlarmStatus 함수 호출
45+
setIsNotificationEnabled(alarmStatus); // 알림 상태 업데이트
46+
console.log("Current Notification Status:", alarmStatus); // 알림 상태 로그 출력
47+
} catch (error) {
48+
console.error("알림 상태 불러오기 오류:", error);
49+
}
50+
};
4551
const toggleNotification = async () => {
4652
const newValue = !isNotificationEnabled; // 상태 반전
4753
setIsNotificationEnabled(newValue);
54+
4855
try {
49-
await AsyncStorage.setItem("notificationEnabled", newValue.toString());
50-
console.log(newValue);
56+
// 서버로 상태 변경 요청
57+
await toggleAlarmStatus(); // 알림 상태 토글
58+
console.log("Notification status:", newValue);
5159
} catch (error) {
52-
console.error("알림 설정 저장 오류:", error);
60+
console.error("알림 상태 변경 오류:", error);
61+
setIsNotificationEnabled(!newValue); // 실패 시 상태 롤백
5362
}
5463
};
64+
5565
const handleUpdatePress = () => {
5666
Linking.openURL("https://apps.apple.com/app/id123456789"); // 스토어 URL로 이동
5767
};
58-
68+
const checkVersionUpdate = async () => {
69+
try {
70+
const minimumVersion = await getMinimumVersion();
71+
setLatestVersion(minimumVersion.versionName); // 서버에서 받아온 최신 버전 설정
72+
setIsLatestVersion(currentVersion >= minimumVersion.versionName); // 버전 비교
73+
} catch (error) {
74+
console.error("최소 업데이트 필요 버전 조회 오류:", error);
75+
}
76+
};
5977
useEffect(() => {
60-
loadKeywords();
78+
loadNotificationStatus(); // 알림 상태 불러오기
79+
loadKeywords(); // 키워드 목록 불러오기
80+
checkVersionUpdate();
6181
}, []);
6282

6383
return (
@@ -105,7 +125,7 @@ export function Settings({ navigation }: { navigation: any }) {
105125
}}
106126
>
107127
{keywords.map((keyword, index) => (
108-
<KeywordBox key={index} keyword={keyword} disablePress={true} />
128+
<KeywordBox key={index} keyword={keyword} />
109129
))}
110130
</ScrollView>
111131
</View>
@@ -243,8 +263,6 @@ export function Settings({ navigation }: { navigation: any }) {
243263
top: 561,
244264
position: "absolute",
245265
}}
246-
247-
//onPress={() => navigation.navigate("Keyword")}
248266
>
249267
<Text
250268
style={{

app/Home/AlarmPage.tsx

+46-68
Original file line numberDiff line numberDiff line change
@@ -7,84 +7,61 @@ import AlarmCategoryItem from "@/components/home/AlarmCategoryItem";
77
import { useNavigation } from "expo-router";
88
import { Color, Font } from "@/constants/Theme";
99
import { NativeStackNavigationProp } from "react-native-screens/lib/typescript/native-stack/types";
10-
11-
export default function AlarmPage({}: {}) {
10+
import { getKeywords } from "@/service/keyword/getKeywords";
11+
export type NoticeItem = {
12+
id: number;
13+
title: string;
14+
noticeTypeKorean: string;
15+
noticeTypeEnglish: string;
16+
pubDate: string;
17+
viewed: boolean;
18+
url: string;
19+
marked: boolean;
20+
};
21+
export default function AlarmPage() {
1222
const navigation = useNavigation();
1323

14-
const [filteredNotices, setFilteredNotices] = useState<TCategoryList[]>([]); // 필터링된 공지사항
15-
const [hasUnreadNotices, setHasUnreadNotices] = useState<boolean>(false); // 읽지 않은 공지가 있는지
16-
const [unreadCount, setUnreadCount] = useState<number>(0); // 읽지 않은 공지 개수
24+
const [filteredNotices, setFilteredNotices] = useState<NoticeItem[]>([]); // 필터링된 공지사항
1725
const [categoryName, setCategoryName] = useState<string>(""); // 카테고리 이름
26+
const [unreadKeywords, setUnreadKeywords] = useState<{
27+
[key: string]: boolean;
28+
}>({});
1829
const [keywords, setKeywords] = useState<string[]>([]); // 키워드 상태 관리
1930

31+
useEffect(() => {
32+
loadKeywords();
33+
}, []);
34+
2035
const loadKeywords = async () => {
2136
try {
22-
const storedKeywords = await AsyncStorage.getItem("keywords");
23-
const parsedKeywords = storedKeywords ? JSON.parse(storedKeywords) : [];
24-
setKeywords(parsedKeywords);
37+
const keywordList = await getKeywords(); // API로부터 키워드 목록 불러오기
38+
setKeywords(keywordList); // 키워드 상태에 저장
2539
} catch (error) {
2640
console.error("키워드 불러오기 오류:", error);
2741
}
2842
};
2943

30-
useEffect(() => {
31-
loadKeywords();
32-
}, []);
33-
34-
const getViewedNotices = async (category: string) => {
35-
const storageKey = `${category}_viewed`;
36-
const existingNotices = await AsyncStorage.getItem(storageKey);
37-
console.log(`불러온 읽음 상태: ${existingNotices}`); // 로그 추가
38-
39-
return existingNotices ? JSON.parse(existingNotices) : [];
40-
};
41-
42-
const checkUnreadNotices = (notices: TCategoryList[], category: string) => {
43-
const unreadNotices = notices.filter((notice) => !notice.read); // read: false인 공지 필터링
44-
setUnreadCount(unreadNotices.length); // 읽지 않은 공지 개수 설정
45-
const hasUnread = unreadNotices.length > 0;
46-
47-
setHasUnreadNotices(hasUnread);
48-
return hasUnread; // 읽지 않은 공지가 있는지 여부 반환
44+
const updateUnreadStatus = (newUnreadStatus: { [key: string]: boolean }) => {
45+
setUnreadKeywords(newUnreadStatus); // 키워드별로 읽지 않은 상태 업데이트
4946
};
50-
51-
const handleFilterNotices = async (
52-
notices: TCategoryList[],
53-
category: string
54-
) => {
55-
setCategoryName(category); // 카테고리 이름 저장
56-
const viewedNotices = await getViewedNotices(category);
57-
// 각 공지의 읽음 상태 적용
58-
const updatedNotices = notices.map((notice) => ({
59-
...notice,
60-
read: viewedNotices.includes(notice.id),
61-
}));
62-
63-
setFilteredNotices(updatedNotices); // 필터링된 공지사항 업데이트
64-
checkUnreadNotices(updatedNotices, category); // 읽지 않은 공지 여부 체크
47+
const handleFilterNotices = (notices: NoticeItem[]) => {
48+
setFilteredNotices(notices);
6549
};
6650

6751
const handleUpdateList = (id: number) => {
68-
setFilteredNotices((prev) =>
69-
prev.map((notice) =>
70-
notice.id === id ? { ...notice, read: true } : notice
71-
)
52+
const updatedNotices = filteredNotices.map((notice) =>
53+
notice.id === id ? { ...notice, viewed: true } : notice
7254
);
73-
74-
const updateOriginalNotices = async () => {
75-
const key = `${categoryName}_viewed`; // 카테고리 이름 기반으로 읽음 상태 저장
76-
const existingNotices = await AsyncStorage.getItem(key);
77-
let parsedNotices = existingNotices ? JSON.parse(existingNotices) : [];
78-
79-
if (!parsedNotices.includes(id)) {
80-
parsedNotices.push(id);
81-
}
82-
83-
await AsyncStorage.setItem(key, JSON.stringify(parsedNotices));
84-
checkUnreadNotices(filteredNotices, categoryName);
85-
};
86-
87-
updateOriginalNotices();
55+
setFilteredNotices(updatedNotices);
56+
57+
// 모든 공지가 읽혔는지 확인
58+
const allRead = updatedNotices.every((notice) => notice.viewed);
59+
if (allRead) {
60+
// 읽지 않은 공지가 없으면 해당 키워드의 빨간 점 제거
61+
const updatedUnreadStatus = { ...unreadKeywords };
62+
updatedUnreadStatus["keyword"] = false; // 현재 카테고리 키워드에 대해 빨간 점 제거
63+
setUnreadKeywords(updatedUnreadStatus);
64+
}
8865
};
8966

9067
// 모든 카테고리에서 읽지 않은 공지를 확인하는 함수
@@ -94,6 +71,7 @@ export default function AlarmPage({}: {}) {
9471
<AlarmHeader
9572
onFilterNotices={handleFilterNotices} // 필터링된 공지사항을 헤더에서 전달
9673
navigation={navigation}
74+
updateUnreadStatus={updateUnreadStatus}
9775
/>
9876
{keywords.length === 0 ? (
9977
<View
@@ -151,18 +129,18 @@ export default function AlarmPage({}: {}) {
151129
</View>
152130
) : (
153131
<FlatList
154-
style={{
155-
marginBottom: 65,
156-
}}
157-
data={filteredNotices}
158-
keyExtractor={(item) => item.id.toString()}
132+
style={{ marginBottom: 65 }}
133+
data={filteredNotices} // 필터링된 공지사항 데이터
134+
keyExtractor={(item) => item.id.toString()} // 각 항목의 고유 키 설정
159135
renderItem={({ item }) => (
160136
<AlarmCategoryItem
161-
item={item}
137+
item={item} // 각각의 공지사항 항목 전달
162138
categoryKey="keyword"
163-
updateList={handleUpdateList}
139+
updateList={handleUpdateList} // 업데이트 함수 전달
164140
/>
165141
)}
142+
showsVerticalScrollIndicator={false} // 스크롤바 숨김 (선택사항)
143+
contentContainerStyle={{ paddingBottom: 20 }} // 추가 패딩으로 마지막 항목 간격 유지
166144
/>
167145
)}
168146
</View>

app/Home/SearchResultPage.tsx

+26-20
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
77
import { TCategoryList } from "@/types/category";
88
import CategoryItem from "@/components/category/CategoryItem";
99
import { Color, Font } from "@/constants/Theme";
10+
import { getSearchNotices } from "@/service/getSearchNotices";
1011

1112
type SearchResultRouteParams = {
1213
query: string;
@@ -18,15 +19,29 @@ export default function SearchResultPage() {
1819
const navigation = useNavigation();
1920
const SEARCH_HISTORY_KEY = "searchHistory";
2021
const [filteredNotices, setFilteredNotices] = useState<TCategoryList[]>([]);
22+
const [loading, setLoading] = useState<boolean>(false); // 로딩 상태 관리
2123

22-
const handleFilterNotices = (filtered: TCategoryList[]) => {
23-
if (query.trim() === "") {
24-
// 검색어가 없을 때는 빈 배열로 설정
25-
setFilteredNotices([]);
26-
} else {
27-
setFilteredNotices(filtered);
28-
}
24+
const updateList = (id: number) => {
25+
// 공지 목록을 업데이트하는 로직 (예: 읽음 상태 변경)
26+
const updatedNotices = filteredNotices.map((item) =>
27+
item.id === id ? { ...item, read: !item.read } : item
28+
);
29+
setFilteredNotices(updatedNotices); // 업데이트된 공지 목록을 저장
30+
};
31+
32+
const handleSearch = (newSearch: string) => {
33+
setQuery(newSearch); // 검색어 업데이트
34+
saveSearchHistory(newSearch); // 검색어를 저장
2935
};
36+
37+
// const handleFilterNotices = (filtered: TCategoryList[]) => {
38+
// if (query.trim() === "") {
39+
// // 검색어가 없을 때는 빈 배열로 설정
40+
// setFilteredNotices([]);
41+
// } else {
42+
// setFilteredNotices(filtered);
43+
// }
44+
// };
3045
// 새로운 검색어를 저장하는 함수
3146
const saveSearchHistory = async (newSearch: string) => {
3247
try {
@@ -45,27 +60,18 @@ export default function SearchResultPage() {
4560
}
4661
};
4762

48-
const updateList = (id: number) => {
49-
// 공지 목록을 업데이트하는 로직 (예: 읽음 상태 변경)
50-
const updatedNotices = filteredNotices.map((item) =>
51-
item.id === id ? { ...item, read: !item.read } : item
52-
);
53-
setFilteredNotices(updatedNotices); // 업데이트된 공지 목록을 저장
54-
};
55-
56-
const handleSearch = (newSearch: string) => {
57-
setQuery(newSearch); // 검색어 업데이트
58-
saveSearchHistory(newSearch); // 검색어를 저장
59-
handleFilterNotices(filteredNotices); // 필터링된 목록 업데이트
63+
const handleSearchComplete = (searchResults: TCategoryList[]) => {
64+
setFilteredNotices(searchResults); // 검색 완료 후 결과 업데이트
6065
};
6166

6267
return (
6368
<View style={styles.container}>
6469
<ResultSearchHeader
6570
query={query}
6671
handleSearch={handleSearch}
67-
onFilter={handleFilterNotices}
72+
//onFilter={handleFilterNotices}
6873
navigation={navigation}
74+
onSearchComplete={handleSearchComplete}
6975
/>
7076
{filteredNotices.length === 0 ? (
7177
<View

app/Setting/Error.tsx

+22-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, { useState } from "react";
33
import { Color, Font } from "@/constants/Theme";
44
import SettingUsableHeader from "@/components/header/SettingUsableHeader";
55
import Toast from "react-native-toast-message";
6+
import { submitErrorMessage } from "@/service/submitErrorMessage";
67

78
export default function Error({ navigation }: { navigation: any }) {
89
const title = "오류신고";
@@ -19,14 +20,27 @@ export default function Error({ navigation }: { navigation: any }) {
1920
};
2021

2122
// 신고 내용 제출
22-
const handleSubmit = () => {
23-
Toast.show({
24-
type: "success",
25-
text1: "신고되었습니다!",
26-
position: "bottom",
27-
});
28-
setErrorText(""); // 입력 필드 초기화
29-
console.log(errorText);
23+
const handleSubmit = async () => {
24+
try {
25+
// 서버에 신고 내용 전송
26+
await submitErrorMessage(errorText);
27+
28+
// 성공적으로 전송되면 Toast로 알림 표시
29+
Toast.show({
30+
type: "success",
31+
text1: "신고되었습니다!",
32+
position: "bottom",
33+
});
34+
setErrorText(""); // 입력 필드 초기화
35+
} catch (error) {
36+
// 전송 실패 시 Toast로 오류 알림
37+
Toast.show({
38+
type: "error",
39+
text1: "신고 실패",
40+
text2: "다시 시도해주세요.",
41+
position: "bottom",
42+
});
43+
}
3044
};
3145

3246
return (

0 commit comments

Comments
 (0)