api.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /* src/service/api.ts */
  2. import {Criteria, Song} from '@/types/song';
  3. import {API_FIELDS} from '@/constants/apiFields';
  4. // 띄어쓰기를 무시하는 정규화 함수
  5. const normalizeText = (text: string): string => text.replace(/\s/g, '').toLowerCase();
  6. // API 응답 데이터 타입 정의
  7. interface ApiSongResponse {
  8. [key: string]: string; // 동적 키를 위해 인덱스 시그니처 사용
  9. [API_FIELDS.BRAND]: string;
  10. [API_FIELDS.NO]: string;
  11. [API_FIELDS.TITLE]: string;
  12. [API_FIELDS.SINGER]: string;
  13. [API_FIELDS.COMPOSER]: string;
  14. [API_FIELDS.LYRICIST]: string;
  15. [API_FIELDS.RELEASE]: string;
  16. }
  17. export const fetchSongs = async (criteria: Criteria, keyword: string): Promise<Song[]> => {
  18. try {
  19. if (!keyword.trim()) return []; // 빈 검색어 처리
  20. // 검색 키워드 정규화 (띄어쓰기 제거)
  21. const normalizedKeyword = normalizeText(keyword);
  22. // criteria에 따라 적절한 엔드포인트 선택
  23. const endpoint =
  24. criteria === 'title'
  25. ? `https://api.manana.kr/karaoke/song/${normalizedKeyword}.json`
  26. : `https://api.manana.kr/karaoke/singer/${normalizedKeyword}.json`;
  27. const response = await fetch(endpoint);
  28. if (!response.ok) {
  29. throw new Error(`HTTP error! status: ${response.status}`);
  30. }
  31. const data: ApiSongResponse[] = await response.json();
  32. // API 응답 데이터를 Song 타입으로 변환 (키를 상수로 정의)
  33. return data
  34. .filter((item) => item[API_FIELDS.BRAND] === 'tj')
  35. .map((item) => ({
  36. [API_FIELDS.NO]: item[API_FIELDS.NO],
  37. [API_FIELDS.TITLE]: item[API_FIELDS.TITLE],
  38. [API_FIELDS.SINGER]: item[API_FIELDS.SINGER],
  39. }))
  40. .sort((a, b) => {
  41. const aNormalized = normalizeText(a[API_FIELDS.TITLE]);
  42. const bNormalized = normalizeText(b[API_FIELDS.TITLE]);
  43. const aStartsWith = aNormalized.startsWith(normalizedKeyword);
  44. const bStartsWith = bNormalized.startsWith(normalizedKeyword);
  45. if (aStartsWith && !bStartsWith) return -1;
  46. if (!aStartsWith && bStartsWith) return 1;
  47. // 둘 다 앞글자 일치 또는 둘 다 불일치할 경우, 알파벳순 정렬
  48. return aNormalized.localeCompare(bNormalized);
  49. });
  50. } catch (error) {
  51. console.error('Error fetching songs:', error);
  52. return [];
  53. }
  54. };