@uniai-fe/uds-templates 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/styles.css +139 -10
  2. package/package.json +18 -11
  3. package/src/auth/common/complete/Template.tsx +3 -0
  4. package/src/auth/common/complete/types.ts +4 -1
  5. package/src/auth/common/find/markup/CodeStep.tsx +2 -1
  6. package/src/auth/common/find/markup/InfoStep.tsx +2 -1
  7. package/src/auth/common/find/styles/result.scss +1 -1
  8. package/src/auth/find-password/markup/StepResetPassword.tsx +2 -1
  9. package/src/auth/login/markup/FormField.tsx +2 -1
  10. package/src/auth/signup/markup/AccountForm.tsx +2 -1
  11. package/src/auth/signup/markup/Complete.tsx +2 -1
  12. package/src/auth/signup/markup/UserInfoForm.tsx +2 -1
  13. package/src/auth/signup/markup/VerificationForm.tsx +4 -2
  14. package/src/index.scss +1 -0
  15. package/src/index.tsx +1 -0
  16. package/src/modal/core/components/FooterButtons.tsx +4 -1
  17. package/src/modal/templates/Dialog.tsx +4 -2
  18. package/src/modal/types/footer.ts +4 -2
  19. package/src/page-frame/container/index.scss +14 -8
  20. package/src/page-frame/desktop/components/header/Container.tsx +22 -0
  21. package/src/page-frame/desktop/components/header/Section.tsx +20 -0
  22. package/src/page-frame/desktop/components/header/index.tsx +19 -0
  23. package/src/page-frame/desktop/components/header/util/Button.tsx +23 -0
  24. package/src/page-frame/desktop/components/header/util/Container.tsx +18 -0
  25. package/src/page-frame/desktop/components/header/util/Item.tsx +13 -0
  26. package/src/page-frame/desktop/components/header/util/Logout.tsx +26 -0
  27. package/src/page-frame/desktop/components/header/util/setting/Button.tsx +39 -0
  28. package/src/page-frame/desktop/components/index.tsx +15 -0
  29. package/src/page-frame/desktop/components/nav/Button.tsx +24 -0
  30. package/src/page-frame/desktop/components/nav/Container.tsx +70 -0
  31. package/src/page-frame/desktop/components/nav/Logo.tsx +46 -0
  32. package/src/page-frame/desktop/components/nav/index.tsx +5 -0
  33. package/src/page-frame/desktop/components/page/Container.tsx +13 -0
  34. package/src/page-frame/desktop/components/page/ServiceFrame.tsx +15 -0
  35. package/src/page-frame/desktop/components/page/ServiceMain.tsx +13 -0
  36. package/src/page-frame/desktop/components/page/ServiceMainWrapper.tsx +24 -0
  37. package/src/page-frame/desktop/components/page/index.tsx +14 -0
  38. package/src/page-frame/desktop/components/popup/Container.tsx +18 -0
  39. package/src/page-frame/desktop/components/popup/frame/Body.tsx +14 -0
  40. package/src/page-frame/desktop/components/popup/frame/Container.tsx +16 -0
  41. package/src/page-frame/desktop/components/popup/frame/Header.tsx +26 -0
  42. package/src/page-frame/desktop/components/popup/frame/index.tsx +11 -0
  43. package/src/page-frame/desktop/components/popup/index.tsx +9 -0
  44. package/src/page-frame/desktop/index.scss +5 -0
  45. package/src/page-frame/desktop/index.tsx +5 -0
  46. package/src/page-frame/desktop/styles/page/common.scss +40 -0
  47. package/src/page-frame/desktop/styles/page/header.scss +49 -0
  48. package/src/page-frame/desktop/styles/page/nav.scss +128 -0
  49. package/src/page-frame/desktop/styles/popup/popup.scss +45 -0
  50. package/src/page-frame/desktop/styles/variables.scss +28 -0
  51. package/src/page-frame/desktop/types/nav.ts +77 -0
  52. package/src/page-frame/index.tsx +2 -0
  53. package/src/page-frame/mobile/index.scss +1 -1
  54. package/src/page-frame/types/index.ts +69 -0
  55. package/src/weather/apis/index.ts +4 -0
  56. package/src/weather/apis/korea/client.ts +93 -0
  57. package/src/weather/apis/korea/server.ts +253 -0
  58. package/src/weather/apis/open-weather-map/client.ts +69 -0
  59. package/src/weather/apis/open-weather-map/server.ts +134 -0
  60. package/src/weather/components/icon/Address.tsx +13 -0
  61. package/src/weather/components/icon/Weather.tsx +32 -0
  62. package/src/weather/components/index.tsx +7 -0
  63. package/src/weather/components/page-header/Address.tsx +21 -0
  64. package/src/weather/components/page-header/Alert.tsx +42 -0
  65. package/src/weather/components/page-header/Container.tsx +14 -0
  66. package/src/weather/components/page-header/Forecast.tsx +26 -0
  67. package/src/weather/components/page-header/NextDays.tsx +32 -0
  68. package/src/weather/components/page-header/Today.tsx +135 -0
  69. package/src/weather/context/mock.tsx +45 -0
  70. package/src/weather/data/alert-regions-meta.json +1286 -0
  71. package/src/weather/data/response.ts +36 -0
  72. package/src/weather/data/weather-regions-meta.json +9833 -0
  73. package/src/weather/hooks/index.ts +4 -0
  74. package/src/weather/hooks/useOpenWeatherMap.ts +42 -0
  75. package/src/weather/hooks/useWeatherKorea.ts +78 -0
  76. package/src/weather/hooks/useWeatherKoreaAlert.ts +36 -0
  77. package/src/weather/index.tsx +11 -0
  78. package/src/weather/jotai/coordinate.ts +16 -0
  79. package/src/weather/jotai/farm-idx.ts +5 -0
  80. package/src/weather/jotai/index.ts +2 -0
  81. package/src/weather/styles/weather.scss +151 -0
  82. package/src/weather/types/api.ts +215 -0
  83. package/src/weather/types/base.ts +50 -0
  84. package/src/weather/types/index.ts +4 -0
  85. package/src/weather/types/korea.ts +228 -0
  86. package/src/weather/types/open-weather-map.ts +164 -0
  87. package/src/weather/utils/alert.ts +30 -0
  88. package/src/weather/utils/date-time.ts +65 -0
  89. package/src/weather/utils/index.ts +4 -0
  90. package/src/weather/utils/location.ts +161 -0
  91. package/src/weather/utils/validate.ts +9 -0
  92. package/src/weather/utils/weather.ts +304 -0
@@ -0,0 +1,4 @@
1
+ import useOpenWeatherMap from "./useOpenWeatherMap";
2
+ import useWeatherKorea from "./useWeatherKorea";
3
+
4
+ export { useWeatherKorea, useOpenWeatherMap };
@@ -0,0 +1,42 @@
1
+ "use client";
2
+
3
+ import { useAtomValue } from "jotai";
4
+ import { weatherCoordinate } from "../jotai";
5
+ import {
6
+ useQueryWeatherOpenWeatherMapForecast,
7
+ useQueryWeatherOpenWeatherMapNow,
8
+ } from "../apis/open-weather-map/client";
9
+ import { useWeatherMock } from "../context/mock";
10
+
11
+ export default function useOpenWeatherMap() {
12
+ const mock = useWeatherMock();
13
+ const coordinate = useAtomValue(weatherCoordinate);
14
+ const shouldUseMock = Boolean(mock?.openWeather);
15
+ // mock 모드일 때는 Query가 실행되지 않도록 NaN 좌표를 전달한다.
16
+ const queryCoordinate = shouldUseMock
17
+ ? { lat: Number.NaN, lng: Number.NaN }
18
+ : coordinate;
19
+
20
+ const { data: now, isFetching: isFetchingNow } =
21
+ useQueryWeatherOpenWeatherMapNow(queryCoordinate);
22
+ const { data: forecast, isFetching: isFetchingForecast } =
23
+ useQueryWeatherOpenWeatherMapForecast(queryCoordinate);
24
+
25
+ if (mock?.openWeather) {
26
+ return {
27
+ coordinate: mock.openWeather.coordinate,
28
+ now: mock.openWeather.now,
29
+ forecast: mock.openWeather.forecast,
30
+ isFetchingNow: mock.openWeather.isFetchingNow ?? false,
31
+ isFetchingForecast: mock.openWeather.isFetchingForecast ?? false,
32
+ };
33
+ }
34
+
35
+ return {
36
+ coordinate,
37
+ now,
38
+ forecast,
39
+ isFetchingNow,
40
+ isFetchingForecast,
41
+ };
42
+ }
@@ -0,0 +1,78 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect } from "react";
4
+ import { useAtomValue } from "jotai";
5
+ import {
6
+ useQueryWeatherKoreaForecast,
7
+ useQueryWeatherKoreaNow,
8
+ } from "../apis/korea/client"; // 클라이언트 전용 API만 import해 Storybook 번들에서 server 코드를 배제한다.
9
+ import type { API_Req_WeatherKorea } from "../types";
10
+ import { weatherCoordinate } from "../jotai/coordinate";
11
+ import { getWeatherBaseMoments } from "../utils/date-time";
12
+ import { getWeatherGridLocation } from "../utils/location";
13
+ import { useWeatherMock } from "../context/mock";
14
+
15
+ export default function useWeatherKorea() {
16
+ const mock = useWeatherMock();
17
+ const coordinate = useAtomValue(weatherCoordinate);
18
+ const [params, setParams] = useState<{
19
+ [categoryKey: string]: API_Req_WeatherKorea;
20
+ }>({
21
+ now: { nx: 0, ny: 0 },
22
+ forecast: { nx: 0, ny: 0 },
23
+ });
24
+
25
+ useEffect(() => {
26
+ if (mock?.korea) return;
27
+ if (typeof window === "undefined") return;
28
+
29
+ const nowMoments = getWeatherBaseMoments("now");
30
+ const forecastMoments = getWeatherBaseMoments("forecast");
31
+
32
+ async function updater() {
33
+ const grid = await getWeatherGridLocation(coordinate);
34
+ setParams({
35
+ now: {
36
+ ...grid,
37
+ ...nowMoments,
38
+ },
39
+ forecast: {
40
+ ...grid,
41
+ ...forecastMoments,
42
+ },
43
+ });
44
+ }
45
+
46
+ updater();
47
+ }, [coordinate, mock]);
48
+
49
+ const { data: now, isFetching: isFetchingNow } = useQueryWeatherKoreaNow(
50
+ params.now,
51
+ );
52
+
53
+ const { data: forecast, isFetching: isFetchingForecast } =
54
+ useQueryWeatherKoreaForecast(params.forecast);
55
+
56
+ if (mock?.korea) {
57
+ return {
58
+ params: {
59
+ now: { nx: 0, ny: 0 },
60
+ forecast: { nx: 0, ny: 0 },
61
+ },
62
+ coordinate: mock.korea.coordinate,
63
+ now: mock.korea.now,
64
+ forecast: mock.korea.forecast,
65
+ isFetchingNow: mock.korea.isFetchingNow ?? false,
66
+ isFetchingForecast: mock.korea.isFetchingForecast ?? false,
67
+ };
68
+ }
69
+
70
+ return {
71
+ params,
72
+ coordinate,
73
+ now,
74
+ forecast,
75
+ isFetchingNow,
76
+ isFetchingForecast,
77
+ };
78
+ }
@@ -0,0 +1,36 @@
1
+ "use client";
2
+
3
+ import { useMemo } from "react";
4
+ import { useAtomValue } from "jotai";
5
+ import { useQueryWeatherKoreaAlert } from "../apis/korea/client"; // server 번들을 피하기 위해 client 모듈에서 직접 import한다.
6
+ import { weatherFarmIdx } from "../jotai/farm-idx";
7
+ import { useWeatherMock } from "../context/mock";
8
+
9
+ export default function useWeatherKoreaAlert() {
10
+ const mock = useWeatherMock();
11
+ const farm_idx = useAtomValue(weatherFarmIdx);
12
+ const shouldUseMock = Boolean(mock?.koreaAlert);
13
+ const resolvedFarmIdx = farm_idx === 507 || !farm_idx ? 507 : (farm_idx ?? 0);
14
+ const queryFarmIdx = shouldUseMock ? 0 : resolvedFarmIdx;
15
+
16
+ const { data, isFetching } = useQueryWeatherKoreaAlert({
17
+ farm_idx: queryFarmIdx,
18
+ });
19
+
20
+ const alert = useMemo(() => data?.alerts || [], [data]);
21
+
22
+ if (mock?.koreaAlert) {
23
+ // WeatherMockProvider를 사용하면 네트워크 호출 없이 스토리/테스트 전용 alert 데이터를 주입할 수 있다.
24
+ return {
25
+ farm_idx: null,
26
+ alert: mock.koreaAlert.alert?.alerts ?? [],
27
+ isFetching: mock.koreaAlert.isFetching ?? false,
28
+ };
29
+ }
30
+
31
+ return {
32
+ farm_idx: resolvedFarmIdx,
33
+ alert,
34
+ isFetching,
35
+ };
36
+ }
@@ -0,0 +1,11 @@
1
+ // Weather UI 컴포넌트 전용 스타일을 로드한다.
2
+ import "./styles/weather.scss";
3
+
4
+ export * from "./utils";
5
+ export * from "./apis";
6
+ export * from "./jotai";
7
+ export * from "./hooks";
8
+ export * from "./context/mock";
9
+ export * from "./types";
10
+ export { default as WeatherComponents } from "./components";
11
+ export { default as WeatherPageHeaderContainer } from "./components/page-header/Container";
@@ -0,0 +1,16 @@
1
+ "use client";
2
+
3
+ import type { WeatherCoordinate } from "../types";
4
+ import { atomWithReset } from "jotai/utils";
5
+
6
+ export const weatherCoordinate = atomWithReset<WeatherCoordinate>({
7
+ address: null,
8
+ lat: null,
9
+ lng: null,
10
+ });
11
+
12
+ export const harimCoordinate: WeatherCoordinate = {
13
+ address: "전북 익산시",
14
+ lat: 35.9372719,
15
+ lng: 126.9601241,
16
+ };
@@ -0,0 +1,5 @@
1
+ "use client";
2
+
3
+ import { atomWithReset } from "jotai/utils";
4
+
5
+ export const weatherFarmIdx = atomWithReset<number | null>(null);
@@ -0,0 +1,2 @@
1
+ export * from "./coordinate";
2
+ export * from "./farm-idx";
@@ -0,0 +1,151 @@
1
+ .weather-base-container {
2
+ width: fit-content;
3
+ display: flex;
4
+ align-items: center;
5
+
6
+ span {
7
+ font-size: 1.4rem;
8
+ }
9
+ }
10
+
11
+ .weather-base-icon {
12
+ width: 2.5rem;
13
+ height: 2.4rem;
14
+ position: relative;
15
+ }
16
+
17
+ .weather-base-text-info {
18
+ display: flex;
19
+ align-items: center;
20
+
21
+ dt {
22
+ margin-right: 0.8rem;
23
+ font-size: 0;
24
+
25
+ span {
26
+ color: var(--color-cool-gray-35);
27
+ }
28
+ }
29
+
30
+ dd {
31
+ font-size: 0;
32
+ display: flex;
33
+ align-items: flex-start;
34
+
35
+ span {
36
+ color: var(--color-cool-gray-10);
37
+ font-weight: 600;
38
+ }
39
+ }
40
+ }
41
+
42
+ .weather-base-divider {
43
+ width: 1px;
44
+ height: 1.3rem;
45
+ margin: 0 0.8rem;
46
+ background: var(--color-cool-gray-85);
47
+ }
48
+
49
+ .weather-address {
50
+ display: flex;
51
+ align-items: center;
52
+ width: fit-content;
53
+
54
+ &-icon {
55
+ width: 1.6rem;
56
+ height: 1.6rem;
57
+ margin-right: 0.4rem;
58
+ position: relative;
59
+ }
60
+
61
+ &-text {
62
+ width: fit-content;
63
+ margin-right: 1rem;
64
+ display: flex;
65
+ align-items: center;
66
+
67
+ span {
68
+ font-size: 1.6rem;
69
+ color: var(--color-cool-gray-10);
70
+ font-weight: 600;
71
+ white-space: nowrap;
72
+ transform: translateY(0.1rem);
73
+ }
74
+ }
75
+ }
76
+
77
+ .weather-today-container {
78
+ @extend .weather-base-container;
79
+
80
+ span {
81
+ white-space: nowrap;
82
+ }
83
+
84
+ .empty-text {
85
+ font-size: 1.4rem;
86
+ padding-right: 4rem;
87
+ }
88
+ }
89
+
90
+ .weather-today-temperature {
91
+ margin-left: 1rem;
92
+ display: flex;
93
+ align-items: flex-start;
94
+
95
+ span {
96
+ font-size: 2rem;
97
+ font-weight: 700;
98
+ color: var(--color-blue-55);
99
+ }
100
+
101
+ .unit {
102
+ font-size: 1.2rem;
103
+ }
104
+ }
105
+
106
+ .weather-today-humidity {
107
+ margin-left: 1.4rem;
108
+ }
109
+
110
+ .weather-alert {
111
+ width: fit-content;
112
+ height: 2.6rem;
113
+ padding: 0 1rem;
114
+ margin-left: 1rem;
115
+ border-radius: 0.8rem;
116
+ background-color: var(--color-cool-gray-95, #f4f6f8);
117
+ display: flex;
118
+ align-items: center;
119
+
120
+ &-text {
121
+ height: fit-content;
122
+ font-size: 0;
123
+
124
+ span {
125
+ font-size: 1.2rem;
126
+ color: var(--color-blue-55, #007cdb);
127
+ font-weight: 600;
128
+ line-height: 1.6;
129
+ }
130
+ }
131
+ }
132
+
133
+ .weather-next-days-container {
134
+ @extend .weather-base-container;
135
+ }
136
+
137
+ .weather-next-days-text {
138
+ @extend .weather-base-text-info;
139
+
140
+ dt {
141
+ margin-right: 0.8rem;
142
+ }
143
+
144
+ dd:nth-of-type(n + 2) {
145
+ margin-left: 0.8rem;
146
+
147
+ .unit {
148
+ font-size: 1rem;
149
+ }
150
+ }
151
+ }
@@ -0,0 +1,215 @@
1
+ import type {
2
+ KMA_Res_WeatherNow,
3
+ KMA_Res_WeatherForecast,
4
+ KMA_Res_Base,
5
+ KMA_Req_BaseGridCoordinate,
6
+ KMA_Req_BaseMoments,
7
+ KMA_Res_AlertType,
8
+ KMA_Res_AlertLevel,
9
+ KMA_Res_AlertCommand,
10
+ KMA_Res_WeatherItem,
11
+ } from "./korea";
12
+
13
+ export type API_Req_WeatherKoreaGrid = KMA_Req_BaseGridCoordinate;
14
+ export type API_Req_WeatherKoreaMoments = KMA_Req_BaseMoments;
15
+
16
+ /**
17
+ * 기상청 API; 날씨 요청.
18
+ */
19
+ export type API_Req_WeatherKorea = API_Req_WeatherKoreaGrid &
20
+ Partial<API_Req_WeatherKoreaMoments>;
21
+
22
+ /**
23
+ * 기상청 API; 특보 요청 파라미터
24
+ * @property {number | null} farm_idx 농장 식별자
25
+ */
26
+ export type API_Req_WeatherKoreaAlert = { farm_idx: number | null };
27
+
28
+ /**
29
+ * 기상청 API; 특보 응답 타입 - 지역별 특보정보
30
+ */
31
+ export type API_Res_WeatherKoreaAlertEach = {
32
+ /**
33
+ * 상위 지역 코드
34
+ * @see https://apihub.kma.go.kr/api/typ01/url/wrn_reg.php?tmfc=0&authKey=njld-D40Rb25Xfg-NAW9hA
35
+ */
36
+ upper_region_code: string;
37
+ /**
38
+ * 상위 지역 이름
39
+ * @see https://apihub.kma.go.kr/api/typ01/url/wrn_reg.php?tmfc=0&authKey=njld-D40Rb25Xfg-NAW9hA
40
+ */
41
+ upper_region_name: string;
42
+ /**
43
+ * 특보 지역 코드
44
+ * @see https://apihub.kma.go.kr/api/typ01/url/wrn_reg.php?tmfc=0&authKey=njld-D40Rb25Xfg-NAW9hA
45
+ */
46
+ alert_region_code: string;
47
+ /**
48
+ * 특보 지역 이름
49
+ * @see https://apihub.kma.go.kr/api/typ01/url/wrn_reg.php?tmfc=0&authKey=njld-D40Rb25Xfg-NAW9hA
50
+ */
51
+ alert_region_name: string;
52
+ /**
53
+ * 특보 발표시간
54
+ * - yyyymmddhhmm
55
+ */
56
+ announcement_time: string;
57
+ /**
58
+ * 특보 발효시간
59
+ * - yyyymmddhhmm
60
+ */
61
+ effective_time: string;
62
+ /** * 특보 종류 (한글) */
63
+ alert_type: KMA_Res_AlertType;
64
+ /**
65
+ * 특보 수준 (한글)
66
+ * - 경보, 주의, 예비
67
+ */
68
+ alert_level: KMA_Res_AlertLevel;
69
+ /**
70
+ * 특보 명령 (한글)
71
+ * - 발표, 변경, 해제
72
+ */
73
+ alert_command: KMA_Res_AlertCommand;
74
+ /**
75
+ * 특보 해제 예고시점 (한글)
76
+ * - dd일 오전/오후/밤(HH시 ~ HH시)
77
+ */
78
+ cancel_notice_time: string;
79
+ };
80
+ /**
81
+ * 기상청 API; 특보 응답 타입
82
+ */
83
+ export type API_Res_WeatherKoreaAlert = {
84
+ /** * 특보 발표 시간 */
85
+ api_announcement_time: string | null;
86
+ /** * 총 특보 개수 */
87
+ total_count: number;
88
+ /** * 지역별 특보 */
89
+ alerts: API_Res_WeatherKoreaAlertEach[];
90
+ };
91
+
92
+ /**
93
+ * 기상청 API; 기초 정보
94
+ * @property {string} condition - 개황 정보
95
+ */
96
+ export type API_Res_WeatherKoreaBase = {
97
+ /**
98
+ * 하늘상태 코드
99
+ * - 1(맑음)
100
+ * - 2(구름조금)
101
+ * - 3(구름많음)
102
+ * - 4(흐림)
103
+ */
104
+ sky: string | null;
105
+ /**
106
+ * 강수형태 코드
107
+ * - 0(없음)
108
+ * - 1(비)
109
+ * - 2(비/눈)
110
+ * - 3(눈)
111
+ * - 4(소나기)
112
+ */
113
+ drop: string | null;
114
+ /**
115
+ * 강수량 코드
116
+ * - 1(약한 비); 3mm/h 미만
117
+ * - 2(보통 비); 3mm/h 이상 15mm/h 미만
118
+ * - 3(강한 비); 15mm/h 이상
119
+ */
120
+ rainAmount: string | null;
121
+ /**
122
+ * 강설량 코드
123
+ * - 1(보통 눈); 1cm/h 미만
124
+ * - 2(많은 눈); 1cm/h 이상
125
+ */
126
+ snowAmount: string | null;
127
+ /**
128
+ * 풍속 코드
129
+ * - 1(약한 바람); 4m/s 미만
130
+ * - 2(약간 강한 바람); 4m/s 이상 9m/s 미만
131
+ * - 3(강한 바람); 9m/s 이상
132
+ */
133
+ windSpeed: string | null;
134
+ /**
135
+ * 날씨 상태 코드
136
+ * - sky-1(맑음)
137
+ * - sky-2(구름조금)
138
+ * - sky-3(구름많음)
139
+ * - sky-4(흐림)
140
+ * - drop-rain-shower(소나기)
141
+ * - drop-rain(비)
142
+ * - drop-rain-1(약한 비)
143
+ * - drop-rain-2(보통 비)
144
+ * - drop-rain-3(강한 비)
145
+ * - drop-rain-snow(비/눈)
146
+ * - drop-rain-snow-1(약한 비/눈)
147
+ * - drop-rain-snow-2(보통 비/눈)
148
+ * - drop-rain-snow-3(강한 비/눈)
149
+ * - drop-snow(눈)
150
+ * - drop-snow-1(보통 눈)
151
+ * - drop-snow-2(많은 눈)
152
+ */
153
+ condition: string | null;
154
+ /** 날씨 상태 텍스트 */
155
+ conditionName: string | null;
156
+ };
157
+
158
+ /**
159
+ * 기상청 API; 오늘 날씨
160
+ * @property {number|string|null} temperature 기온(℃)
161
+ * @property {number|string|null} humidity 습도(%)
162
+ */
163
+ export type API_Res_WeatherKoreaToday = API_Res_WeatherKoreaBase & {
164
+ /** 기온(℃) */
165
+ temperature: number | string | null;
166
+ /** 습도(%) */
167
+ humidity: number | string | null;
168
+ };
169
+
170
+ /**
171
+ * 기상청 API; 내일/모레 날씨
172
+ * @property {number|string|null} max_temperature 최고기온(℃)
173
+ * @property {number|string|null} min_temperature 최저기온(℃)
174
+ */
175
+ export type API_Res_WeatherKoreaNextDays = API_Res_WeatherKoreaBase & {
176
+ /** 최고 기온(℃) */
177
+ max_temperature: number | string | null;
178
+ /** 최저 기온(℃) */
179
+ min_temperature: number | string | null;
180
+ };
181
+
182
+ /**
183
+ * 기상청 API; 원본 응답
184
+ * @property {RAW} raw API 원본 데이터
185
+ */
186
+ export type API_Res_WeatherKoreaRaw<RAW = KMA_Res_Base<KMA_Res_WeatherItem>> = {
187
+ /** API 원본 */
188
+ raw: RAW;
189
+ };
190
+
191
+ /**
192
+ * 기상청 API; 초단기 실황 구조
193
+ * @property {API_Res_WeatherKoreaToday} today 오늘 데이터
194
+ */
195
+ export type API_Res_WeatherKoreaNow =
196
+ API_Res_WeatherKoreaRaw<KMA_Res_WeatherNow> & {
197
+ /** 오늘 날씨 */
198
+ today: API_Res_WeatherKoreaToday;
199
+ };
200
+
201
+ /**
202
+ * 기상청 API; 단기 예보 구조
203
+ * @property {API_Res_WeatherKoreaToday} today 오늘 데이터
204
+ * @property {API_Res_WeatherKoreaNextDays} day_1 내일 데이터
205
+ * @property {API_Res_WeatherKoreaNextDays} day_2 모레 데이터
206
+ */
207
+ export type API_Res_WeatherKoreaForecast =
208
+ API_Res_WeatherKoreaRaw<KMA_Res_WeatherForecast> & {
209
+ /** 오늘 날씨 */
210
+ today: API_Res_WeatherKoreaToday;
211
+ /** 내일 날씨 */
212
+ day_1: API_Res_WeatherKoreaNextDays;
213
+ /** 모레 날씨 */
214
+ day_2: API_Res_WeatherKoreaNextDays;
215
+ };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * 위경도 좌표.
3
+ * @property {number | null} latitude 위도
4
+ * @property {number | null} longitude 경도
5
+ */
6
+ export type GeoCoordinate = {
7
+ /** 위도 */
8
+ latitude: number | null;
9
+ /** 경도 */
10
+ longitude: number | null;
11
+ };
12
+
13
+ /**
14
+ * 날씨 API에서 사용하는 위경도 좌표.
15
+ * @property {number | null} lat 위도
16
+ * @property {number | null} lng 경도
17
+ */
18
+ export type WeatherGeoCoordinate = {
19
+ /** 위도 */
20
+ lat: number | null;
21
+ /** 경도 */
22
+ lng: number | null;
23
+ };
24
+
25
+ /**
26
+ * 좌표와 주소 정보를 함께 담는 구조.
27
+ * @property {string | null} address 좌표 주소
28
+ */
29
+ export type WeatherCoordinate = {
30
+ /** 좌표 주소 */
31
+ address: string | null;
32
+ } & WeatherGeoCoordinate;
33
+
34
+ /**
35
+ * 날씨 로직에서 사용하는 날짜 기준값 모음.
36
+ * @property {Date} now 현재 시각
37
+ * @property {string} today 오늘 날짜(yyyymmdd)
38
+ * @property {string} tomorrow 내일 날짜(yyyymmdd)
39
+ * @property {string} dayAfterTomorrow 모레 날짜(yyyymmdd)
40
+ */
41
+ export type WeatherUtilDateTimeMoments = {
42
+ /** 현재 시각 */
43
+ now: Date;
44
+ /** 오늘 날짜(yyyymmdd) */
45
+ today: string;
46
+ /** 내일 날짜(yyyymmdd) */
47
+ tomorrow: string;
48
+ /** 모레 날짜(yyyymmdd) */
49
+ dayAfterTomorrow: string;
50
+ };
@@ -0,0 +1,4 @@
1
+ export type * from "./base";
2
+ export type * from "./api";
3
+ export type * from "./korea";
4
+ export type * from "./open-weather-map";