@uniai-fe/uds-templates 0.5.29 → 0.6.1

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 (54) hide show
  1. package/README.md +3 -6
  2. package/package.json +1 -1
  3. package/src/weather/_legacy/apis/index.ts +4 -0
  4. package/src/weather/_legacy/data/response.ts +36 -0
  5. package/src/weather/_legacy/hooks/index.ts +5 -0
  6. package/src/weather/{hooks → _legacy/hooks}/useOpenWeatherMap.ts +1 -1
  7. package/src/weather/{hooks → _legacy/hooks}/useWeatherKorea.ts +4 -7
  8. package/src/weather/{hooks → _legacy/hooks}/useWeatherKoreaAlert.ts +2 -4
  9. package/src/weather/_legacy/types/api.ts +221 -0
  10. package/src/weather/_legacy/types/base.ts +70 -0
  11. package/src/weather/_legacy/types/index.ts +4 -0
  12. package/src/weather/_legacy/utils/index.ts +5 -0
  13. package/src/weather/_legacy/utils/locale.ts +28 -0
  14. package/src/weather/_legacy/utils/location.ts +139 -0
  15. package/src/weather/_legacy/utils/weather.ts +460 -0
  16. package/src/weather/apis/client.ts +459 -0
  17. package/src/weather/apis/index.ts +2 -4
  18. package/src/weather/apis/server.ts +373 -0
  19. package/src/weather/components/icon/Address.tsx +7 -0
  20. package/src/weather/components/icon/Weather.tsx +7 -6
  21. package/src/weather/components/page-header/Address.tsx +14 -0
  22. package/src/weather/components/page-header/Alert.tsx +17 -13
  23. package/src/weather/components/page-header/Container.tsx +12 -19
  24. package/src/weather/components/page-header/Forecast.tsx +21 -28
  25. package/src/weather/components/page-header/NextDays.tsx +10 -0
  26. package/src/weather/components/page-header/Today.tsx +86 -158
  27. package/src/weather/components/page-header/index.ts +5 -0
  28. package/src/weather/data/response.ts +4 -23
  29. package/src/weather/hooks/index.ts +3 -3
  30. package/src/weather/hooks/useWeather.ts +52 -0
  31. package/src/weather/hooks/useWeatherAlert.ts +35 -0
  32. package/src/weather/index.tsx +2 -2
  33. package/src/weather/jotai/coordinate.ts +4 -0
  34. package/src/weather/jotai/farm-idx.ts +4 -0
  35. package/src/weather/types/api.ts +442 -114
  36. package/src/weather/types/base.ts +31 -32
  37. package/src/weather/types/index.ts +0 -3
  38. package/src/weather/types/page-header.ts +118 -68
  39. package/src/weather/utils/index.ts +6 -4
  40. package/src/weather/utils/locale.ts +7 -69
  41. package/src/weather/utils/location.ts +47 -102
  42. package/src/weather/utils/weather.ts +53 -456
  43. package/src/weather/data/alert-regions-meta.json +0 -1286
  44. package/src/weather/data/weather-regions-meta.json +0 -9833
  45. package/src/weather/types/provider.ts +0 -34
  46. package/src/weather/utils/alert.ts +0 -30
  47. /package/src/weather/{apis → _legacy/apis}/korea/client.ts +0 -0
  48. /package/src/weather/{apis → _legacy/apis}/korea/server.ts +0 -0
  49. /package/src/weather/{apis → _legacy/apis}/open-weather-map/client.ts +0 -0
  50. /package/src/weather/{apis → _legacy/apis}/open-weather-map/server.ts +0 -0
  51. /package/src/weather/{types → _legacy/types}/korea.ts +0 -0
  52. /package/src/weather/{types → _legacy/types}/open-weather-map.ts +0 -0
  53. /package/src/weather/{utils → _legacy/utils}/date-time.ts +0 -0
  54. /package/src/weather/{utils → _legacy/utils}/validate.ts +0 -0
@@ -1,18 +1,17 @@
1
1
  import type {
2
2
  GeoCoordinate,
3
- KMA_GridCoordinate,
4
- KMA_Req_BaseGridCoordinate,
5
- WeatherCoordinate,
3
+ WeatherGeoCoordinate,
4
+ WeatherGridCoordinate,
6
5
  } from "../types";
7
6
 
8
7
  /**
9
- * 날씨 도구; 접속위치 추출
8
+ * 날씨 도구; 접속위치 추출.
10
9
  * @util
11
- * @return {GeoCoordinate}}
10
+ * @desc 브라우저 geolocation API에서 현재 위치를 읽고, 사용할 수 없으면 null 좌표를 반환한다.
11
+ * @return {Promise<GeoCoordinate>} 브라우저 geolocation에서 읽은 위경도
12
12
  */
13
13
  export const userLocation = async (): Promise<GeoCoordinate> => {
14
14
  if (typeof window === "undefined" || !window.navigator.geolocation) {
15
- // console.log("[userLocation] window 없음");
16
15
  return { latitude: null, longitude: null };
17
16
  }
18
17
 
@@ -22,12 +21,11 @@ export const userLocation = async (): Promise<GeoCoordinate> => {
22
21
  window.navigator.geolocation.getCurrentPosition(resolve, reject);
23
22
  },
24
23
  );
25
- // console.log("[userLocation] 위치 정보:", position.coords);
26
- const res = {
24
+
25
+ return {
27
26
  latitude: position.coords.latitude,
28
27
  longitude: position.coords.longitude,
29
28
  };
30
- return res;
31
29
  } catch (error) {
32
30
  console.error("[userLocation] 위치 정보 에러", error);
33
31
  return { latitude: null, longitude: null };
@@ -35,41 +33,36 @@ export const userLocation = async (): Promise<GeoCoordinate> => {
35
33
  };
36
34
 
37
35
  /**
38
- * 날씨 도구; 위경도 -> 격자 좌표 변환
36
+ * 날씨 도구; 위경도 좌표를 backend weather 격자 좌표로 변환한다.
39
37
  * @util
40
- * @param {GeoCoordinate} coordinate - 위경도 좌표
41
- * @param {number} coordinate.latitude - 위도
42
- * @param {number} coordinate.longitude - 경도
43
- * @return {KMA_GridCoordinate} 격자 좌표
44
- * @desc
45
- * - 위경도 좌표를 기상청 격자 좌표로 변환합니다.
46
- * - 출처: 기상청
47
- * @see https://apihub.kma.go.kr/
48
- * @see https://apihub.kma.go.kr/getAttachFile.do?fileName=%EB%8B%A8%EA%B8%B0%EC%98%88%EB%B3%B4%20%EC%A1%B0%ED%9A%8C%EC%84%9C%EB%B9%84%EC%8A%A4_API%ED%99%9C%EC%9A%A9%EA%B0%80%EC%9D%B4%EB%93%9C_241128.docx
38
+ * @param {GeoCoordinate} coordinate 위경도 좌표
39
+ * @param {number|null} coordinate.latitude 위도
40
+ * @param {number|null} coordinate.longitude 경도
41
+ * @return {WeatherGridCoordinate} backend weather 격자 좌표
49
42
  */
50
- export function convertCoordinateToGrid({
43
+ export const convertCoordinateToGrid = ({
51
44
  latitude,
52
45
  longitude,
53
- }: GeoCoordinate): KMA_GridCoordinate {
54
- const res: KMA_GridCoordinate = { x: 0, y: 0 };
46
+ }: GeoCoordinate): WeatherGridCoordinate => {
47
+ const fallback: WeatherGridCoordinate = { nx: null, ny: null };
55
48
 
56
- if (latitude === null || longitude === null) return res;
49
+ if (latitude === null || longitude === null) return fallback;
57
50
 
58
- const RE = 6371.00877; // Earth radius (km)
59
- const GRID = 5.0; // Grid spacing (km)
60
- const SLAT1 = 30.0; // Projection latitude 1 (degree)
61
- const SLAT2 = 60.0; // Projection latitude 2 (degree)
62
- const ORIGIN_LONGITUDE = 126.0; // Origin longitude (degree)
63
- const ORIGIN_LATITUDE = 38.0; // Origin latitude (degree)
64
- const XO = 43; // Origin X coordinate (GRID)
65
- const YO = 136; // Origin Y coordinate (GRID)
51
+ const RE = 6371.00877;
52
+ const GRID = 5.0;
53
+ const SLAT1 = 30.0;
54
+ const SLAT2 = 60.0;
55
+ const ORIGIN_LONGITUDE = 126.0;
56
+ const ORIGIN_LATITUDE = 38.0;
57
+ const XO = 43;
58
+ const YO = 136;
66
59
 
67
60
  const RADIAN = Math.PI / 180.0;
68
61
  const re = RE / GRID;
69
62
  const slat1 = SLAT1 * RADIAN;
70
63
  const slat2 = SLAT2 * RADIAN;
71
- const origin_longitude = ORIGIN_LONGITUDE * RADIAN;
72
- const origin_latitude = ORIGIN_LATITUDE * RADIAN;
64
+ const originLongitude = ORIGIN_LONGITUDE * RADIAN;
65
+ const originLatitude = ORIGIN_LATITUDE * RADIAN;
73
66
 
74
67
  const sn =
75
68
  Math.log(Math.cos(slat1) / Math.cos(slat2)) /
@@ -80,85 +73,37 @@ export function convertCoordinateToGrid({
80
73
 
81
74
  const sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
82
75
  const sfPow = (Math.pow(sf, sn) * Math.cos(slat1)) / sn;
83
-
84
76
  const ro =
85
77
  (re * sfPow) /
86
- Math.pow(Math.tan(Math.PI * 0.25 + origin_latitude * 0.5), sn);
87
-
78
+ Math.pow(Math.tan(Math.PI * 0.25 + originLatitude * 0.5), sn);
88
79
  const ra =
89
80
  (re * sfPow) /
90
81
  Math.pow(Math.tan(Math.PI * 0.25 + latitude * RADIAN * 0.5), sn);
91
- let theta = longitude * RADIAN - origin_longitude;
82
+ let theta = longitude * RADIAN - originLongitude;
83
+
92
84
  if (theta > Math.PI) theta -= 2.0 * Math.PI;
93
85
  if (theta < -Math.PI) theta += 2.0 * Math.PI;
94
86
  theta *= sn;
95
87
 
96
- res.x = Math.floor(ra * Math.sin(theta) + XO + 0.5);
97
- res.y = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5);
98
-
99
- // console.log("[WEATHER] 위/경도 -> 기상청 격자값", res);
100
-
101
- return res;
102
- }
88
+ return {
89
+ nx: Math.floor(ra * Math.sin(theta) + XO + 0.5),
90
+ ny: Math.floor(ro - ra * Math.cos(theta) + YO + 0.5),
91
+ };
92
+ };
103
93
 
104
94
  /**
105
- * 날씨 도구; 위도/경도 -> 기상청 격자 좌표 변환
95
+ * 날씨 도구; weather 위경도 좌표를 backend weather 격자 좌표로 변환한다.
106
96
  * @util
107
- * @param {WeatherCoordinate} [coordinate] - 사용자 위치 이외의 특정 위도/경도 좌표
108
- * @param {number} coordinate.lat - 위도
109
- * @param {number} coordinate.lng - 경도
110
- * @return {KMA_Req_BaseGridCoordinate} 기상청 격자 좌표
97
+ * @param {Partial<WeatherGeoCoordinate>} coordinate weather 위경도 좌표
98
+ * @param {number|null} [coordinate.lat] 위도
99
+ * @param {number|null} [coordinate.lng] 경도
100
+ * @return {WeatherGridCoordinate} backend weather 격자 좌표
111
101
  */
112
- export async function getWeatherGridLocation(
113
- coordinate?: WeatherCoordinate,
114
- ): Promise<KMA_Req_BaseGridCoordinate> {
115
- const res: KMA_Req_BaseGridCoordinate = { nx: 0, ny: 0 };
116
-
117
- if (typeof window === "undefined") return res;
118
-
119
- const geo: GeoCoordinate = {
120
- latitude: coordinate?.lat ?? null,
121
- longitude: coordinate?.lng ?? null,
122
- };
123
- const hasInjectedAddress =
124
- typeof coordinate?.address === "string" && coordinate.address.trim() !== "";
125
-
126
- // console.log("[getWeatherLocation] 특정 좌표지정 확인", coordinate);
127
-
128
- // 변경 설명: 서비스가 address만 명시적으로 주입한 경우에는 geolocation fallback을 재시도하지 않는다.
129
- if (
130
- typeof window !== "undefined" &&
131
- !hasInjectedAddress &&
132
- (typeof coordinate === "undefined" ||
133
- geo.latitude === null ||
134
- geo.longitude === null)
135
- ) {
136
- const { latitude, longitude } = await userLocation();
137
-
138
- if (latitude === null || longitude === null) {
139
- // console.log("[getWeatherLocation] window.navigator 실패", geo);
140
- return res;
141
- }
142
- geo.latitude = latitude;
143
- geo.longitude = longitude;
144
- // console.log("[getWeatherLocation] 사용자 위치", geo);
145
- }
146
-
147
- // 위경도 좌표를 기상청 격자좌표로 변환
148
- const grid = convertCoordinateToGrid(geo);
149
-
150
- if (grid.x === 0 || grid.y === 0) {
151
- // console.error("[getWeatherLocation] 위치 정보를 가져오는데 실패했습니다.", {
152
- // latitude: geo.latitude,
153
- // longitude: geo.longitude,
154
- // });
155
- return res;
156
- }
157
- // console.log("[getWeatherLocation] 기상청 격자좌표", grid);
158
-
159
- res.nx = grid.x;
160
- res.ny = grid.y;
161
-
162
- // console.log("[getWeatherLocation] result", res);
163
- return res;
164
- }
102
+ export const convertWeatherCoordinateToGrid = ({
103
+ lat,
104
+ lng,
105
+ }: Partial<WeatherGeoCoordinate>): WeatherGridCoordinate =>
106
+ convertCoordinateToGrid({
107
+ latitude: lat ?? null,
108
+ longitude: lng ?? null,
109
+ });