backup 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import React, { useState } from 'react';
  2. import {
  3. View,
  4. Text,
  5. TextInput,
  6. TouchableOpacity,
  7. FlatList,
  8. StyleSheet,
  9. } from 'react-native';
  10. import AsyncStorage from '@react-native-async-storage/async-storage';
  11. import { useRouter } from 'expo-router';
  12. interface Song {
  13. id: string;
  14. title: string;
  15. artist: string;
  16. }
  17. const MOCK_SONGS: Song[] = [
  18. { id: '1234', title: '좋은 날', artist: '아이유' },
  19. { id: '5678', title: '취중진담', artist: '김동률' },
  20. { id: '9101', title: 'LOVE DIVE', artist: 'IVE' },
  21. { id: '1121', title: 'Permission to Dance', artist: 'BTS' },
  22. ];
  23. export default function MainScreen() {
  24. const [keyword, setKeyword] = useState('');
  25. const [results, setResults] = useState<Song[]>([]);
  26. const router = useRouter();
  27. const handleSearch = () => {
  28. const filtered = MOCK_SONGS.filter(
  29. song =>
  30. song.title.includes(keyword) ||
  31. song.artist.includes(keyword)
  32. );
  33. setResults(filtered);
  34. };
  35. const handleAddToFavorites = async (song: Song) => {
  36. const stored = await AsyncStorage.getItem('favorites');
  37. const parsed = stored ? JSON.parse(stored) : [];
  38. await AsyncStorage.setItem('favorites', JSON.stringify([...parsed, song]));
  39. };
  40. return (
  41. <View style={styles.container}>
  42. <View style={styles.navbar}>
  43. <TouchableOpacity onPress={() => {}}>
  44. <Text style={styles.icon}>👤</Text>
  45. </TouchableOpacity>
  46. <TouchableOpacity onPress={() => {}}>
  47. <Text style={styles.icon}>⭐️</Text>
  48. </TouchableOpacity>
  49. <TouchableOpacity onPress={() => {}}>
  50. <Text style={styles.icon}>⚙️</Text>
  51. </TouchableOpacity>
  52. </View>
  53. {/* 타이틀 */}
  54. <Text style={styles.title}>Sing Song</Text>
  55. {/* 검색 영역 */}
  56. <TextInput
  57. placeholder="제목 또는 가수를 입력하세요"
  58. value={keyword}
  59. onChangeText={setKeyword}
  60. style={styles.input}
  61. />
  62. <TouchableOpacity onPress={handleSearch} style={styles.searchButton}>
  63. <Text style={styles.searchText}>검색</Text>
  64. </TouchableOpacity>
  65. {/* 검색 결과 리스트 */}
  66. <FlatList
  67. data={results}
  68. keyExtractor={(item) => item.id}
  69. renderItem={({ item }) => (
  70. <TouchableOpacity onPress={() => handleAddToFavorites(item)}>
  71. <View style={styles.item}>
  72. <Text>{item.id} - {item.title} ({item.artist})</Text>
  73. </View>
  74. </TouchableOpacity>
  75. )}
  76. ListEmptyComponent={<Text>검색 결과가 없습니다.</Text>}
  77. />
  78. </View>
  79. );
  80. }
  81. const styles = StyleSheet.create({
  82. container: {
  83. flex: 1,
  84. padding: 20,
  85. backgroundColor: '#fff',
  86. },
  87. navbar: {
  88. flexDirection: 'row',
  89. justifyContent: 'flex-end',
  90. gap: 16,
  91. marginBottom: 8,
  92. },
  93. icon: {
  94. fontSize: 20,
  95. },
  96. title: {
  97. fontSize: 24,
  98. fontWeight: 'bold',
  99. marginBottom: 16,
  100. },
  101. settings: {
  102. fontSize: 20,
  103. },
  104. input: {
  105. borderWidth: 1,
  106. borderColor: '#ccc',
  107. borderRadius: 8,
  108. padding: 8,
  109. marginBottom: 10,
  110. },
  111. searchButton: {
  112. backgroundColor: '#007AFF',
  113. padding: 10,
  114. borderRadius: 8,
  115. alignItems: 'center',
  116. marginBottom: 16,
  117. },
  118. searchText: {
  119. color: '#fff',
  120. fontWeight: 'bold',
  121. },
  122. item: {
  123. padding: 12,
  124. borderBottomWidth: 1,
  125. borderBottomColor: '#eee',
  126. },
  127. });