Skip to content

Commit c9b7157

Browse files
committed
Merge branch 'develop'
2 parents 3eba01c + ba1ecf8 commit c9b7157

Some content is hidden

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

70 files changed

+4040
-2044
lines changed

.github/ISSUE_TEMPLATE/bug-report.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
name: Bug report
3+
about: 개발 서버 오류
4+
title: "[bug]"
5+
labels: "\U0001F41BBug"
6+
assignees: ''
7+
8+
---
9+
10+
## 🐛 오류 내용
11+
12+
- bugs
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
name: Feature request
3+
about: 신규 기능 구현
4+
title: "[feature]"
5+
labels: "\U0001F4ABFeature"
6+
assignees: ''
7+
8+
---
9+
10+
## 📌 설명
11+
12+
## 🛠️ 구현 목록
13+
14+
✅ 구체적으로 작성하기
15+
16+
- [ ] TODO
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
name: Hotfix report
3+
about: 운영 서버 오류
4+
title: "[hotfix]"
5+
labels: "\U0001FA93Hotfix"
6+
assignees: ''
7+
8+
---
9+
10+
## 🐛 오류 내용
11+
12+
- bugs

.github/pull_request_template.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## 📌 간단 설명
2+
3+
한 줄 설명
4+
5+
## ✅ 변경 내용
6+
7+
- 변경 내용 (issues)

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@
4444

4545
### System Architecture
4646

47-
![System Architecture](https://github.com/LikeKNU/.github/assets/69714701/0fe21330-7475-4d55-a4a7-f8bd8fec8cdd)
47+
![System Architecture](https://github.com/LikeKNU/LikeKNU/assets/69714701/c014ad62-fb3a-4fa6-a62a-c8b6f2d74d4c)

api/bus.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useCampus } from '@/common/contexts/CampusContext';
22
import { Campuses, campusName } from '@/constants/campus';
3-
import { CityBusProps, ShuttleBusProps, ShuttleRouteProps } from '@/types/busTypes';
3+
import { CityBusProps, CityBusRouteProps, ShuttleBusProps, ShuttleRouteProps } from '@/types/busTypes';
44
import { ValueNameType } from '@/types/common';
55
import http, { extractBodyFromResponse } from '@/utils/http';
66
import useSWR from 'swr';
@@ -37,3 +37,24 @@ export const useShuttleBuses = (shuttleId: string) => {
3737

3838
return useSWR(`/api/buses/shuttle-bus/${shuttleId}`, getShuttleBuses);
3939
};
40+
41+
export const useCityBusRoutes = () => {
42+
const { campus } = useCampus();
43+
const getCityBusRoutes = async (uri: string, campus: Campuses | null) => {
44+
if (campus) {
45+
const response = await http.getWithParams<CityBusRouteProps[]>(uri, { campus: campusName[campus].value });
46+
return extractBodyFromResponse<CityBusRouteProps[]>(response) ?? [];
47+
}
48+
};
49+
50+
return useSWR(['/api/buses/city-bus/routes', campus], ([uri, campus]) => getCityBusRoutes(uri, campus));
51+
};
52+
53+
export const useCityBusArrivalTime = (routeId: string) => {
54+
const getCityBusArrivalTime = async (uri: string) => {
55+
const response = await http.get<CityBusProps>(uri);
56+
return extractBodyFromResponse<CityBusProps>(response);
57+
};
58+
59+
return useSWR(`/api/buses/city-bus/${routeId}/arrival-time`, getCityBusArrivalTime);
60+
}

api/home.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useCampus } from '@/common/contexts/CampusContext';
22
import { Campuses, campusName } from '@/constants/campus';
33
import { HomeAnnouncementProps, HomeBusProps, HomeCalendarProps, HomeMealProps } from '@/types/homeType';
4-
import http, { extractBodyFromResponse } from '@/utils/http';
4+
import http, { extractBodyFromResponse, extractMessageFromResponse } from '@/utils/http';
55
import useSWR from 'swr';
66

77
export const useHomeAnnouncements = () => {
@@ -48,3 +48,12 @@ export const useHomeCalendar = () => {
4848

4949
return useSWR('/api/main/schedule', getHomeCalendar);
5050
};
51+
52+
export const useHomeMessage = () => {
53+
const getHomeMessage = async (uri: string) => {
54+
const response = await http.get<string>(uri);
55+
return extractMessageFromResponse(response) ?? '';
56+
};
57+
58+
return useSWR('/api/main/messages', getHomeMessage);
59+
};

api/meal.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import { Campuses, campusName } from '@/constants/campus';
33
import { cafeterias, Cafeterias } from '@/constants/meal';
44
import { MealProps } from '@/types/mealTypes';
55
import http, { extractBodyFromResponse } from '@/utils/http';
6-
import useSWR from 'swr';
6+
import useSWR, { SWRConfiguration } from 'swr';
77

8-
export const useMeals = (cafeteria: Cafeterias) => {
8+
interface UseMealsOptions extends SWRConfiguration {
9+
enabled?: boolean;
10+
}
11+
12+
export const useMeals = (cafeteria: Cafeterias, options: UseMealsOptions = {}) => {
913
const { campus } = useCampus();
1014
const getMeals = async (uri: string, campus: Campuses | null, cafeteria: Cafeterias) => {
1115
if (campus && cafeterias[campus].includes(cafeteria)) {
@@ -17,5 +21,7 @@ export const useMeals = (cafeteria: Cafeterias) => {
1721
}
1822
};
1923

20-
return useSWR(['/api/menus', campus, cafeteria], ([uri, campus, cafeteria]) => getMeals(uri, campus, cafeteria));
24+
const shouldFetch = options.enabled !== false;
25+
26+
return useSWR(shouldFetch ? ['/api/menus', campus, cafeteria] : null, ([uri, campus, cafeteria]) => getMeals(uri, campus, cafeteria));
2127
};

app.json

+73-5
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
"expo": {
33
"name": "공주대처럼",
44
"slug": "like-knu",
5-
"version": "1.0.4",
5+
"version": "1.4.0",
66
"orientation": "portrait",
77
"icon": "./assets/icon.png",
88
"userInterfaceStyle": "automatic",
99
"assetBundlePatterns": [
1010
"**/*"
1111
],
1212
"ios": {
13-
"buildNumber": "1",
13+
"buildNumber": "49",
1414
"splash": {
1515
"image": "./assets/splash.png",
1616
"resizeMode": "contain",
@@ -32,10 +32,11 @@
3232
"CFBundleLocalizations": [
3333
"ko"
3434
]
35-
}
35+
},
36+
"appStoreUrl": "https://apps.apple.com/kr/app/%EA%B3%B5%EC%A3%BC%EB%8C%80%EC%B2%98%EB%9F%BC/id6499512208"
3637
},
3738
"android": {
38-
"versionCode": 24,
39+
"versionCode": 49,
3940
"adaptiveIcon": {
4041
"foregroundImage": "./assets/adaptive-icon.png",
4142
"backgroundColor": "#FFFFFF"
@@ -50,12 +51,14 @@
5051
"backgroundColor": "#101012"
5152
}
5253
},
53-
"package": "ac.knu.likeknu"
54+
"package": "ac.knu.likeknu",
55+
"playStoreUrl": "https://play.google.com/store/apps/details?id=ac.knu.likeknu"
5456
},
5557
"web": {
5658
"favicon": "./assets/favicon.png"
5759
},
5860
"plugins": [
61+
"expo-font",
5962
"expo-router",
6063
"@react-native-firebase/app",
6164
[
@@ -68,6 +71,71 @@
6871
"enableProguardInReleaseBuilds": true
6972
}
7073
}
74+
],
75+
[
76+
"expo-tracking-transparency",
77+
{
78+
"userTrackingPermission": "이 식별자는 개인 맞춤형 광고를 제공하는 데 사용됩니다."
79+
}
80+
],
81+
[
82+
"react-native-google-mobile-ads",
83+
{
84+
"iosAppId": "ca-app-pub-2814557138984161~7500117117",
85+
"androidAppId": "ca-app-pub-2814557138984161~2843844350",
86+
"userTrackingUsageDescription": "이 식별자는 개인 맞춤형 광고를 제공하는 데 사용됩니다.",
87+
"skAdNetworkItems": [
88+
"cstr6suwn9.skadnetwork",
89+
"4fzdc2evr5.skadnetwork",
90+
"4pfyvq9l8r.skadnetwork",
91+
"2fnua5tdw4.skadnetwork",
92+
"ydx93a7ass.skadnetwork",
93+
"5a6flpkh64.skadnetwork",
94+
"p78axxw29g.skadnetwork",
95+
"v72qych5uu.skadnetwork",
96+
"ludvb6z3bs.skadnetwork",
97+
"cp8zw746q7.skadnetwork",
98+
"3sh42y64q3.skadnetwork",
99+
"c6k4g5qg8m.skadnetwork",
100+
"s39g8k73mm.skadnetwork",
101+
"3qy4746246.skadnetwork",
102+
"f38h382jlk.skadnetwork",
103+
"hs6bdukanm.skadnetwork",
104+
"v4nxqhlyqp.skadnetwork",
105+
"wzmmz9fp6w.skadnetwork",
106+
"yclnxrl5pm.skadnetwork",
107+
"t38b2kh725.skadnetwork",
108+
"7ug5zh24hu.skadnetwork",
109+
"gta9lk7p23.skadnetwork",
110+
"vutu7akeur.skadnetwork",
111+
"y5ghdn5j9k.skadnetwork",
112+
"n6fk4nfna4.skadnetwork",
113+
"v9wttpbfk9.skadnetwork",
114+
"n38lu8286q.skadnetwork",
115+
"47vhws6wlr.skadnetwork",
116+
"kbd757ywx3.skadnetwork",
117+
"9t245vhmpl.skadnetwork",
118+
"eh6m2bh4zr.skadnetwork",
119+
"a2p9lx4jpn.skadnetwork",
120+
"22mmun2rn5.skadnetwork",
121+
"4468km3ulz.skadnetwork",
122+
"2u9pt9hc89.skadnetwork",
123+
"8s468mfl3y.skadnetwork",
124+
"klf5c3l5u5.skadnetwork",
125+
"ppxm28t8ap.skadnetwork",
126+
"ecpz2srf59.skadnetwork",
127+
"uw77j35x4d.skadnetwork",
128+
"pwa73g5rt2.skadnetwork",
129+
"mlmmfzh3r3.skadnetwork",
130+
"578prtvx9j.skadnetwork",
131+
"4dzt52r2t5.skadnetwork",
132+
"e5fvkxwrpn.skadnetwork",
133+
"8c4e2ghe7u.skadnetwork",
134+
"zq492l623r.skadnetwork",
135+
"3rd42ekr43.skadnetwork",
136+
"3qcr597p9d.skadnetwork"
137+
]
138+
}
71139
]
72140
],
73141
"scheme": "like-knu",

app/(tabs)/_layout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const TabLayout = () => {
4747
}}>
4848
<Tabs.Screen name="index" options={{
4949
tabBarIcon: ({ color }) => (
50-
<HomeIcon fill={color} width={30} height={30} />
50+
<HomeIcon fill={color} width={29} height={29} />
5151
),
5252
tabBarLabel: ({ color }) => (
5353
<FontText style={[styles.label, { color: color }]}></FontText>

app/_layout.tsx

+13-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import analytics from '@react-native-firebase/analytics';
88
import { useFonts } from 'expo-font';
99
import { Stack, usePathname } from 'expo-router';
1010
import * as SplashScreen from 'expo-splash-screen';
11+
import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
1112
import React, { useCallback, useEffect } from 'react';
1213
import { AppState } from 'react-native';
1314
import { GestureHandlerRootView } from 'react-native-gesture-handler';
15+
import mobileAds from 'react-native-google-mobile-ads';
1416
import { RootSiblingParent } from 'react-native-root-siblings';
1517
import { SafeAreaProvider } from 'react-native-safe-area-context';
1618
import { AppStateStatus } from 'react-native/Libraries/AppState/AppState';
@@ -55,9 +57,7 @@ const AppLayout = () => {
5557
<SWRConfig value={{
5658
provider: () => new Map(),
5759
isVisible: () => true,
58-
initFocus(callback) {
59-
return handleInitFocus(callback);
60-
}
60+
initFocus: (callback) => handleInitFocus(callback)
6161
}}>
6262
<RootSiblingParent>
6363
<ThemeContextProvider>
@@ -82,9 +82,19 @@ const Content = () => {
8282
useInitializeDevice();
8383

8484
useEffect(() => {
85+
requestTrackingPermissionsAsync()
86+
.then(() => {
87+
});
88+
89+
mobileAds()
90+
.initialize()
91+
.then(() => {
92+
});
93+
8594
analytics().logScreenView({
8695
screen_name: pathname,
8796
screen_class: pathname
97+
}).then(() => {
8898
});
8999
}, [pathname]);
90100

app/announcement/Announcement.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useAnnouncements } from '@/api/announcement';
22
import BookmarkIcon from '@/assets/icons/bookmark-fill.svg';
33
import SearchIcon from '@/assets/icons/search.svg';
4+
import AnnouncementBannerAd from '@/common/ads/AnnouncementBannerAd';
45
import AnimatedPressable from '@/common/components/AnimatedPressable';
56
import InfiniteScrollView from '@/common/components/InfiniteScrollView';
67
import PageLayout from '@/common/components/PageLayout';
@@ -56,12 +57,12 @@ const Announcement = () => {
5657
<AnimatedPressable style={styles.bookmarkPressable}
5758
animatedViewStyle={styles.bookmarkAnimatedPressable}
5859
onPress={() => router.push('/announcement/bookmark')}>
59-
<BookmarkIcon width={20} height={20} fill={colors[theme].gray200} />
60+
<BookmarkIcon width={22} height={22} fill={colors[theme].gray200} />
6061
</AnimatedPressable>
6162
<AnimatedPressable style={styles.searchPressable}
6263
animatedViewStyle={styles.searchAnimatedPressable}
6364
onPress={() => router.push('/announcement/search')}>
64-
<SearchIcon width={20} height={20} fill={colors[theme].gray200} />
65+
<SearchIcon width={22} height={22} fill={colors[theme].gray200} />
6566
</AnimatedPressable>
6667
</View>
6768
</TabHeader>
@@ -70,6 +71,7 @@ const Announcement = () => {
7071
activeTab={category}
7172
tabItems={Object.values(categories).map(value => value)}
7273
/>
74+
<AnnouncementBannerAd />
7375
<InfiniteScrollView
7476
data={announcements}
7577
handleEndReached={loadMore}

app/announcement/components/AnnouncementItem.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import FontText from '@/common/text/FontText';
66
import colors from '@/constants/colors';
77
import { AnnouncementProps } from '@/types/announcementType';
88
import { getCurrentDate } from '@/utils/date';
9+
import analytics from '@react-native-firebase/analytics';
910
import { useRouter } from 'expo-router';
1011
import { useEffect, useState } from 'react';
1112
import { StyleSheet, View } from 'react-native';
@@ -23,12 +24,17 @@ const AnnouncementItem = ({ announcement }: { announcement: AnnouncementProps })
2324
}, [announcement]);
2425

2526
const handlePress = () => {
27+
analytics().logSelectContent({
28+
content_type: 'select_announcement',
29+
item_id: `${announcement.announcementId}`
30+
});
31+
2632
router.push({
2733
pathname: '/announcement/details',
2834
params: {
2935
url: announcement.announcementUrl,
3036
id: announcement.announcementId,
31-
isBookmark: isBookmark
37+
isBookmark: String(isBookmark)
3238
}
3339
});
3440
};
@@ -51,7 +57,7 @@ const AnnouncementItem = ({ announcement }: { announcement: AnnouncementProps })
5157
<FontText style={[{ color: colors[theme].gray100 }, styles.additional]}>
5258
{announcement.announcementTag + ' | ' + announcement.announcementDate}
5359
</FontText>
54-
{isToday && <DotIcon fill={colors.red} width={14} height={14} />}
60+
{isToday && <DotIcon fill={colors[theme].red} width={14} height={14} />}
5561
</View>
5662
</View>
5763
<View style={{ flex: 1, alignItems: 'flex-end' }}>

app/announcement/components/AnnouncementSearch.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import FontText from '@/common/text/FontText';
77
import colors from '@/constants/colors';
88
import { AnnouncementProps } from '@/types/announcementType';
99
import { flatMapRemoveDuplicate } from '@/utils/data';
10+
import analytics from '@react-native-firebase/analytics';
1011
import { usePathname } from 'expo-router';
1112
import { useEffect, useState } from 'react';
1213
import { Keyboard, KeyboardAvoidingView, Platform, StyleSheet } from 'react-native';
@@ -38,6 +39,11 @@ const AnnouncementSearch = () => {
3839
};
3940

4041
const handleSubmit = (keyword: string) => {
42+
if (keyword.length !== 0) {
43+
analytics().logSearch({
44+
search_term: keyword
45+
});
46+
}
4147
setKeyword(keyword);
4248
};
4349

0 commit comments

Comments
 (0)