cutechicken commited on
Commit
3c3a731
ยท
verified ยท
1 Parent(s): c48c3d4

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +219 -199
index.html CHANGED
@@ -47,12 +47,73 @@
47
  color: white;
48
  -webkit-text-stroke: 1px #333;
49
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  </style>
51
  </head>
52
  <body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  <div class="container" id="cardsContainer"></div>
54
 
55
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  // Hugging Face์˜ spaces/models URL ๋ชฉ๋ก
57
  const urls = [
58
  "https://huggingface.co/spaces/ginipick/Tech_Hangman_Game",
@@ -64,161 +125,8 @@
64
  "https://huggingface.co/spaces/VIDraft/PHI4-Multimodal",
65
  "https://huggingface.co/spaces/ginigen/Ovis2-8B",
66
  "https://huggingface.co/spaces/ginigen/Graph-Mind",
67
-
68
- "https://huggingface.co/spaces/ginigen/Workflow-Canvas",
69
- "https://huggingface.co/spaces/ginigen/Design",
70
- "https://huggingface.co/spaces/ginigen/Diagram",
71
- "https://huggingface.co/spaces/ginigen/Mockup",
72
- "https://huggingface.co/spaces/ginigen/Infographic",
73
- "https://huggingface.co/spaces/ginigen/Flowchart",
74
- "https://huggingface.co/spaces/aiqcamp/FLUX-Vision",
75
- "https://huggingface.co/spaces/ginigen/VoiceClone-TTS",
76
- "https://huggingface.co/spaces/openfree/Perceptron-Network",
77
- "https://huggingface.co/spaces/openfree/Article-Generator",
78
- "https://huggingface.co/spaces/openfree/Math-Game",
79
- "https://huggingface.co/spaces/openfree/PDF-TTS",
80
- "https://huggingface.co/spaces/openfree/chess",
81
- "https://huggingface.co/spaces/fantos/Panorama",
82
- "https://huggingface.co/spaces/ginigen/Multi-LoRAgen",
83
- "https://huggingface.co/spaces/ginigen/canvas-studio",
84
- "https://huggingface.co/spaces/ginipick/Fashion-Style",
85
- "https://huggingface.co/spaces/ginipick/Time-Stream",
86
- "https://huggingface.co/spaces/ginipick/AccuVision-Diffusion",
87
- "https://huggingface.co/spaces/fantos/Magic-Drawings",
88
- "https://huggingface.co/spaces/ginigen/Lumina-Image-PLUS",
89
- "https://huggingface.co/spaces/fantaxy/fantasy-novel",
90
- "https://huggingface.co/spaces/fantaxy/eros",
91
- "https://huggingface.co/spaces/fantaxy/adult-novel",
92
- "https://huggingface.co/spaces/fantaxy/kungfu-novel",
93
- "https://huggingface.co/spaces/fantaxy/love-novel",
94
- "https://huggingface.co/spaces/VIDraft/mouse-webgen",
95
- "https://huggingface.co/spaces/immunobiotech/MUSIC-Jukebox",
96
- "https://huggingface.co/spaces/seawolf2357/Flowise-AI",
97
- "https://huggingface.co/spaces/ginigen/Flux-LayerDiffuse",
98
- "https://huggingface.co/spaces/VIDraft/Portrait-Animation",
99
- "https://huggingface.co/spaces/VIDraft/Deepseek-Multimodal",
100
- "https://huggingface.co/spaces/VIDraft/BLIP2",
101
- "https://huggingface.co/spaces/ginigen/text3d-r1",
102
- "https://huggingface.co/spaces/immunobiotech/drug-discovery",
103
- "https://huggingface.co/spaces/openfree/VisionOCR-Chat",
104
- "https://huggingface.co/spaces/immunobiotech/MICHELIN",
105
- "https://huggingface.co/spaces/immunobiotech/MICHELIN-korea",
106
- "https://huggingface.co/spaces/immunobiotech/MICHELIN-japan",
107
- "https://huggingface.co/spaces/immunobiotech/MICHELIN-china",
108
- "https://huggingface.co/spaces/VIDraft/money-radar-korea",
109
- "https://huggingface.co/spaces/VIDraft/money-radar",
110
- "https://huggingface.co/spaces/ginipick/PharmAI-Korea",
111
- "https://huggingface.co/spaces/ginigen/MagicFace-V3",
112
- "https://huggingface.co/spaces/aiqcamp/MindMap",
113
- "https://huggingface.co/spaces/ginigen/3D-LLAMA",
114
- "https://huggingface.co/spaces/openfree/VectorFlow",
115
- "https://huggingface.co/spaces/openfree/webtoon-gen",
116
- "https://huggingface.co/spaces/VIDraft/topic-prediction",
117
- "https://huggingface.co/spaces/VIDraft/PapersImpact",
118
- "https://huggingface.co/spaces/VIDraft/EveryRAG",
119
- "https://huggingface.co/spaces/VIDraft/korea-president-DJ",
120
- "https://huggingface.co/spaces/VIDraft/korea-president-PARK",
121
- "https://huggingface.co/spaces/openfree/image-to-vector",
122
- "https://huggingface.co/spaces/ginipick/QR-Canvas-plus",
123
- "https://huggingface.co/spaces/ginigen/text3d-R1",
124
- "https://huggingface.co/spaces/openfree/MagicFace-V3",
125
- "https://huggingface.co/spaces/ginipick/DeepSeekR1-LIVE",
126
- "https://huggingface.co/spaces/ginigen/ColPali-multi",
127
- "https://huggingface.co/spaces/ginigen/Janus-Pro-7B",
128
- "https://huggingface.co/spaces/ginigen/Animagine",
129
- "https://huggingface.co/spaces/openfree/PDF-RAG",
130
- "https://huggingface.co/spaces/fantos/Ranking-Tracker",
131
- "https://huggingface.co/spaces/aiqcamp/Multilingual-Images",
132
- "https://huggingface.co/spaces/aiqcamp/Gemini2-Flash-Thinking",
133
- "https://huggingface.co/spaces/openfree/pepe",
134
- "https://huggingface.co/spaces/openfree/korea-president-yoon",
135
- "https://huggingface.co/spaces/openfree/CryptoVision",
136
- "https://huggingface.co/spaces/fantos/VoiceClone",
137
- "https://huggingface.co/spaces/seawolf2357/ocrlatex",
138
- "https://huggingface.co/spaces/seawolf2357/img2vid",
139
- "https://huggingface.co/spaces/seawolf2357/sd-prompt-gen",
140
- "https://huggingface.co/spaces/openfree/tarotcard",
141
- "https://huggingface.co/spaces/aiqcamp/Polaroid",
142
- "https://huggingface.co/spaces/ginigen/cartoon",
143
- "https://huggingface.co/spaces/ginigen/Book-Cover",
144
- "https://huggingface.co/spaces/aiqcamp/fash",
145
- "https://huggingface.co/spaces/gunship999/Korea-Daily-News",
146
- "https://huggingface.co/spaces/immunobiotech/ChicagoGallery",
147
- "https://huggingface.co/spaces/immunobiotech/MetropolitanMuseum",
148
- "https://huggingface.co/spaces/immunobiotech/opensky",
149
- "https://huggingface.co/spaces/aiqtech/FLUX-military",
150
- "https://huggingface.co/spaces/fantaxy/Rolls-Royce",
151
- "https://huggingface.co/spaces/seawolf2357/flux-korea-hanbok-lora",
152
- "https://huggingface.co/spaces/seawolf2357/flux-korea-palace-lora",
153
- "https://huggingface.co/spaces/aiqcamp/flux-cat-lora",
154
- "https://huggingface.co/spaces/gunship999/SexyImages",
155
- "https://huggingface.co/spaces/aiqtech/flux-claude-monet-lora",
156
- "https://huggingface.co/spaces/seawolf2357/3D-Avatar-Generator",
157
- "https://huggingface.co/spaces/fantaxy/playground25",
158
- "https://huggingface.co/spaces/openfree/ultpixgen",
159
- "https://huggingface.co/spaces/seawolf2357/REALVISXL-V5",
160
- "https://huggingface.co/spaces/fantos/flxcontrol",
161
- "https://huggingface.co/spaces/ginipick/FLUX-Prompt-Generator",
162
- "https://huggingface.co/spaces/fantaxy/flxloraexp",
163
- "https://huggingface.co/spaces/fantos/flxloraexp",
164
- "https://huggingface.co/spaces/seawolf2357/flxloraexp",
165
- "https://huggingface.co/spaces/ginipick/flxloraexp",
166
- "https://huggingface.co/spaces/fantos/textcutobject",
167
- "https://huggingface.co/spaces/aiqcamp/imagemagic",
168
- "https://huggingface.co/spaces/openfree/ColorRevive",
169
- "https://huggingface.co/spaces/VIDraft/RAGOndevice",
170
- "https://huggingface.co/spaces/aiqcamp/AudioLlama",
171
- "https://huggingface.co/spaces/ginigen/FLUXllama-Multilingual",
172
- "https://huggingface.co/openfree/president-k-dj",
173
- "https://huggingface.co/openfree/president-pjh",
174
- "https://huggingface.co/openfree/flux-lora-korea-palace",
175
- "https://huggingface.co/seawolf2357/hanbok",
176
- "https://huggingface.co/seawolf2357/ntower",
177
- "https://huggingface.co/openfree/pepe",
178
- "https://huggingface.co/openfree/korea-president-yoon",
179
- "https://huggingface.co/seawolf2357/flux-lora-military-artillery-k9",
180
- "https://huggingface.co/openfree/claude-monet",
181
- "https://huggingface.co/ginipick/flux-lora-eric-cat",
182
- "https://huggingface.co/seawolf2357/flux-lora-car-rolls-royce",
183
- "https://huggingface.co/spaces/aiqcamp/Fashion-FLUX",
184
- "https://huggingface.co/spaces/fantaxy/flx-pulid",
185
- "https://huggingface.co/spaces/fantaxy/flx-upscale",
186
- "https://huggingface.co/spaces/fantos/flx8lora",
187
- "https://huggingface.co/spaces/ginipick/FitGen",
188
- "https://huggingface.co/spaces/fantaxy/FLUX-Animations",
189
- "https://huggingface.co/spaces/fantaxy/Remove-Video-Background",
190
- "https://huggingface.co/spaces/fantaxy/ofai-flx-logo",
191
- "https://huggingface.co/spaces/fantos/x-mas",
192
- "https://huggingface.co/spaces/openfree/Korean-Leaderboard",
193
- "https://huggingface.co/spaces/ginipick/FLUXllama",
194
- "https://huggingface.co/spaces/fantaxy/Sound-AI-SFX",
195
- "https://huggingface.co/spaces/openfree/trending-board",
196
- "https://huggingface.co/spaces/ginipick/Realtime-FLUX",
197
- "https://huggingface.co/spaces/aiqtech/kofaceid",
198
- "https://huggingface.co/spaces/fantaxy/fastvideogen",
199
- "https://huggingface.co/spaces/fantos/flxfashmodel",
200
- "https://huggingface.co/spaces/fantos/kolcontrl",
201
- "https://huggingface.co/spaces/aiqtech/imaginpaint",
202
- "https://huggingface.co/spaces/ginipick/spaces-research-korea",
203
- "https://huggingface.co/spaces/ginipick/spaces-research-think",
204
- "https://huggingface.co/spaces/VIDraft/mouse-Visual-Chat",
205
- "https://huggingface.co/spaces/VIDraft/mouse-file-chat",
206
- "https://huggingface.co/spaces/openfree/Datasets-Convertor",
207
- "https://huggingface.co/spaces/openfree/Parquet-CSV-Convertor",
208
- "https://huggingface.co/spaces/ginigen/FLUX-Eternity",
209
- "https://huggingface.co/spaces/ginipick/live-detect-pose",
210
- "https://huggingface.co/spaces/ginigen/OmniParser-v2-pro",
211
- "https://huggingface.co/spaces/ginigen/Celebrity",
212
- "https://huggingface.co/spaces/ginigen/Fashion-Pose-Control",
213
- "https://huggingface.co/spaces/ginigen/zonos-longform",
214
- "https://huggingface.co/spaces/aiqtech/cinevid",
215
- "https://huggingface.co/spaces/aiqtech/FLUX-Ghibli-Studio-LoRA",
216
- "https://huggingface.co/spaces/aiqtech/flxgif",
217
- "https://huggingface.co/spaces/ginipick/3D-GAME",
218
- "https://huggingface.co/spaces/ginipick/Flipper-Code-Generator",
219
- "https://huggingface.co/spaces/ginipick/Baby-Name-Generator",
220
- "https://huggingface.co/spaces/ginipick/secreen-capture-OCR",
221
- "https://huggingface.co/spaces/ginipick/face-pose-detect"
222
  ];
223
 
224
  // URL์˜ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„์„ ์ œ๋ชฉ์œผ๋กœ ์ถ”์ถœ (์–ธ๋”๋ฐ”, ํ•˜์ดํ”ˆ์„ ๊ณต๋ฐฑ์œผ๋กœ ๋ณ€ํ™˜)
@@ -228,58 +136,170 @@
228
  return title.replace(/[_-]/g, " ");
229
  }
230
 
231
- // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์‚ฌ์šฉํ•ด ์ข‹์•„์š” ์ƒํƒœ(์‚ฌ์šฉ์ž๋ณ„)๋ฅผ ์ €์žฅ (์˜ˆ์ œ์šฉ)
232
- const likedUrls = JSON.parse(localStorage.getItem("likedUrls")) || {};
233
-
234
- function toggleLike(url, button) {
235
- if (likedUrls[url]) {
236
- delete likedUrls[url];
237
- button.classList.remove("liked");
238
- button.classList.add("not-liked");
239
- } else {
240
- likedUrls[url] = true;
241
- button.classList.add("liked");
242
- button.classList.remove("not-liked");
243
- }
244
- localStorage.setItem("likedUrls", JSON.stringify(likedUrls));
245
  }
246
 
247
- const container = document.getElementById("cardsContainer");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
- // ๊ฐ URL์— ๋Œ€ํ•ด ์นด๋“œ ์ƒ์„ฑ
250
- urls.forEach(url => {
251
- const card = document.createElement("div");
252
- card.className = "card";
 
 
 
 
 
 
 
 
253
 
254
- // ์ œ๋ชฉ
255
- const titleEl = document.createElement("h3");
256
- titleEl.textContent = extractTitle(url);
257
- card.appendChild(titleEl);
 
 
 
 
 
 
258
 
259
- // URL ๋งํฌ
260
- const linkEl = document.createElement("a");
261
- linkEl.href = url;
262
- linkEl.textContent = url;
263
- linkEl.target = "_blank";
264
- card.appendChild(linkEl);
265
 
266
- // ์ข‹์•„์š” ๋ฒ„ํŠผ (โ™ฅ ์•„์ด์ฝ˜)
267
- const likeBtn = document.createElement("button");
268
- likeBtn.className = "like-button";
269
- likeBtn.textContent = "โ™ฅ";
270
- if (likedUrls[url]) {
271
- likeBtn.classList.add("liked");
272
- } else {
273
- likeBtn.classList.add("not-liked");
 
 
 
 
 
 
 
 
 
 
 
274
  }
275
- likeBtn.addEventListener("click", function(e) {
276
- e.preventDefault(); // ๋งํฌ ํด๋ฆญ ๋ฐฉ์ง€
277
- toggleLike(url, likeBtn);
278
- });
279
- card.appendChild(likeBtn);
 
280
 
281
- container.appendChild(card);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  });
 
 
 
 
 
 
 
 
 
 
 
 
283
  </script>
284
  </body>
285
- </html>
 
47
  color: white;
48
  -webkit-text-stroke: 1px #333;
49
  }
50
+ /* ๋กœ๊ทธ์ธ ์ƒํƒœ ํ‘œ์‹œ ๋ฐ ์ปจํŠธ๋กค */
51
+ .user-controls {
52
+ padding: 1rem;
53
+ margin-bottom: 1rem;
54
+ background-color: #f0f0f0;
55
+ border-radius: 5px;
56
+ display: flex;
57
+ justify-content: space-between;
58
+ align-items: center;
59
+ }
60
+ /* ๋กœ๋”ฉ ํ‘œ์‹œ */
61
+ .loading {
62
+ position: fixed;
63
+ top: 0;
64
+ left: 0;
65
+ right: 0;
66
+ bottom: 0;
67
+ background-color: rgba(255, 255, 255, 0.7);
68
+ display: flex;
69
+ justify-content: center;
70
+ align-items: center;
71
+ z-index: 1000;
72
+ font-size: 1.5rem;
73
+ display: none;
74
+ }
75
  </style>
76
  </head>
77
  <body>
78
+ <!-- ๋กœ๊ทธ์ธ ์ƒํƒœ ๋ฐ ์‚ฌ์šฉ์ž ์ปจํŠธ๋กค -->
79
+ <div class="user-controls" id="userControls">
80
+ <div>
81
+ <span>๋กœ๊ทธ์ธ: </span>
82
+ <span id="loginStatus">๋กœ๊ทธ์ธ๋˜์ง€ ์•Š์Œ</span>
83
+ </div>
84
+ <div>
85
+ <input type="text" id="usernameInput" placeholder="์‚ฌ์šฉ์ž ์ด๋ฆ„" />
86
+ <button id="loginButton">๋กœ๊ทธ์ธ</button>
87
+ <button id="logoutButton" style="display: none;">๋กœ๊ทธ์•„์›ƒ</button>
88
+ </div>
89
+ </div>
90
+
91
+ <!-- ๋กœ๋”ฉ ํ‘œ์‹œ -->
92
+ <div class="loading" id="loadingIndicator">
93
+ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘...
94
+ </div>
95
+
96
+ <!-- ์นด๋“œ ์ปจํ…Œ์ด๋„ˆ -->
97
  <div class="container" id="cardsContainer"></div>
98
 
99
  <script>
100
+ // ์ƒํƒœ ๊ด€๋ฆฌ
101
+ const state = {
102
+ currentUser: null,
103
+ likedUrls: {},
104
+ isLoading: false
105
+ };
106
+
107
+ // DOM ์š”์†Œ ์ฐธ์กฐ
108
+ const elements = {
109
+ loginStatus: document.getElementById('loginStatus'),
110
+ usernameInput: document.getElementById('usernameInput'),
111
+ loginButton: document.getElementById('loginButton'),
112
+ logoutButton: document.getElementById('logoutButton'),
113
+ cardsContainer: document.getElementById('cardsContainer'),
114
+ loadingIndicator: document.getElementById('loadingIndicator')
115
+ };
116
+
117
  // Hugging Face์˜ spaces/models URL ๋ชฉ๋ก
118
  const urls = [
119
  "https://huggingface.co/spaces/ginipick/Tech_Hangman_Game",
 
125
  "https://huggingface.co/spaces/VIDraft/PHI4-Multimodal",
126
  "https://huggingface.co/spaces/ginigen/Ovis2-8B",
127
  "https://huggingface.co/spaces/ginigen/Graph-Mind",
128
+ // ์ „์ฒด URL ๋ชฉ๋ก ์ค‘ ์ผ๋ถ€๋งŒ ํ‘œ์‹œ (์‹ค์ œ๋กœ๋Š” ๋ชจ๋“  URL์„ ํฌํ•จํ•ด์•ผ ํ•จ)
129
+ // ... ๋‚˜๋จธ์ง€ URL
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  ];
131
 
132
  // URL์˜ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„์„ ์ œ๋ชฉ์œผ๋กœ ์ถ”์ถœ (์–ธ๋”๋ฐ”, ํ•˜์ดํ”ˆ์„ ๊ณต๋ฐฑ์œผ๋กœ ๋ณ€ํ™˜)
 
136
  return title.replace(/[_-]/g, " ");
137
  }
138
 
139
+ // ๋กœ๋”ฉ ์ƒํƒœ ํ‘œ์‹œ ํ•จ์ˆ˜
140
+ function setLoading(isLoading) {
141
+ state.isLoading = isLoading;
142
+ elements.loadingIndicator.style.display = isLoading ? 'flex' : 'none';
143
+ }
144
+
145
+ // ์‚ฌ์šฉ์ž ์ข‹์•„์š” ๋ฐ์ดํ„ฐ ์ €์žฅ (์„œ๋ฒ„ API ํ˜ธ์ถœ๋กœ ๋Œ€์ฒด ๊ฐ€๋Šฅ)
146
+ function saveLikes(username, likes) {
147
+ return new Promise((resolve) => {
148
+ // ์‹ค์ œ ๊ตฌํ˜„์—์„œ๋Š” ์„œ๋ฒ„ API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ DB์— ์ €์žฅ
149
+ // ์˜ˆ์‹œ๋กœ localStorage๋ฅผ ์‚ฌ์šฉ (์‚ฌ์šฉ์ž๋ณ„ ์ข‹์•„์š” ๋ฐ์ดํ„ฐ ์ €์žฅ)
150
+ localStorage.setItem(`likes_${username}`, JSON.stringify(likes));
151
+ setTimeout(resolve, 300); // ๋„คํŠธ์›Œํฌ ์ง€์—ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
152
+ });
153
  }
154
 
155
+ // ์‚ฌ์šฉ์ž ์ข‹์•„์š” ๋ฐ์ดํ„ฐ ๋กœ๋“œ (์„œ๋ฒ„ API ํ˜ธ์ถœ๋กœ ๋Œ€์ฒด ๊ฐ€๋Šฅ)
156
+ function loadLikes(username) {
157
+ return new Promise((resolve) => {
158
+ // ์‹ค์ œ ๊ตฌํ˜„์—์„œ๋Š” ์„œ๋ฒ„ API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ DB์—์„œ ๋ถˆ๋Ÿฌ์˜ด
159
+ // ์˜ˆ์‹œ๋กœ localStorage๋ฅผ ์‚ฌ์šฉ
160
+ const likes = JSON.parse(localStorage.getItem(`likes_${username}`)) || {};
161
+ setTimeout(() => resolve(likes), 300); // ๋„คํŠธ์›Œํฌ ์ง€์—ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
162
+ });
163
+ }
164
+
165
+ // ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ
166
+ async function login(username) {
167
+ if (!username.trim()) {
168
+ alert('์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.');
169
+ return;
170
+ }
171
+
172
+ setLoading(true);
173
+
174
+ try {
175
+ // ์‚ฌ์šฉ์ž ์ข‹์•„์š” ๋ฐ์ดํ„ฐ ๋กœ๋“œ
176
+ const likes = await loadLikes(username);
177
+
178
+ // ์ƒํƒœ ์—…๋ฐ์ดํŠธ
179
+ state.currentUser = username;
180
+ state.likedUrls = likes;
181
+
182
+ // UI ์—…๋ฐ์ดํŠธ
183
+ elements.loginStatus.textContent = `${username}๋‹˜์œผ๋กœ ๋กœ๊ทธ์ธ๋จ`;
184
+ elements.usernameInput.style.display = 'none';
185
+ elements.loginButton.style.display = 'none';
186
+ elements.logoutButton.style.display = 'inline-block';
187
+
188
+ // ์นด๋“œ ๋‹ค์‹œ ๋ Œ๋”๋ง
189
+ renderCards();
190
+ } catch (error) {
191
+ alert('๋กœ๊ทธ์ธ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.');
192
+ console.error('๋กœ๊ทธ์ธ ์˜ค๋ฅ˜:', error);
193
+ } finally {
194
+ setLoading(false);
195
+ }
196
+ }
197
 
198
+ // ๋กœ๊ทธ์•„์›ƒ ์ฒ˜๋ฆฌ
199
+ function logout() {
200
+ // ์ƒํƒœ ์ดˆ๊ธฐํ™”
201
+ state.currentUser = null;
202
+ state.likedUrls = {};
203
+
204
+ // UI ์—…๋ฐ์ดํŠธ
205
+ elements.loginStatus.textContent = '๋กœ๊ทธ์ธ๋˜์ง€ ์•Š์Œ';
206
+ elements.usernameInput.style.display = 'inline-block';
207
+ elements.usernameInput.value = '';
208
+ elements.loginButton.style.display = 'inline-block';
209
+ elements.logoutButton.style.display = 'none';
210
 
211
+ // ์นด๋“œ ๋‹ค์‹œ ๋ Œ๋”๋ง
212
+ renderCards();
213
+ }
214
+
215
+ // ์ข‹์•„์š” ํ† ๊ธ€ ์ฒ˜๋ฆฌ
216
+ async function toggleLike(url, button) {
217
+ if (!state.currentUser) {
218
+ alert('์ข‹์•„์š”๋ฅผ ํ•˜๋ ค๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.');
219
+ return;
220
+ }
221
 
222
+ setLoading(true);
 
 
 
 
 
223
 
224
+ try {
225
+ // ์ข‹์•„์š” ์ƒํƒœ ํ† ๊ธ€
226
+ if (state.likedUrls[url]) {
227
+ delete state.likedUrls[url];
228
+ button.classList.remove("liked");
229
+ button.classList.add("not-liked");
230
+ } else {
231
+ state.likedUrls[url] = true;
232
+ button.classList.add("liked");
233
+ button.classList.remove("not-liked");
234
+ }
235
+
236
+ // ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ €์žฅ
237
+ await saveLikes(state.currentUser, state.likedUrls);
238
+ } catch (error) {
239
+ alert('์ข‹์•„์š” ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.');
240
+ console.error('์ข‹์•„์š” ์˜ค๋ฅ˜:', error);
241
+ } finally {
242
+ setLoading(false);
243
  }
244
+ }
245
+
246
+ // ์นด๋“œ ๋ Œ๋”๋ง
247
+ function renderCards() {
248
+ // ์นด๋“œ ์ปจํ…Œ์ด๋„ˆ ์ดˆ๊ธฐํ™”
249
+ elements.cardsContainer.innerHTML = '';
250
 
251
+ // ๊ฐ URL์— ๋Œ€ํ•ด ์นด๋“œ ์ƒ์„ฑ
252
+ urls.forEach(url => {
253
+ const card = document.createElement("div");
254
+ card.className = "card";
255
+
256
+ // ์ œ๋ชฉ
257
+ const titleEl = document.createElement("h3");
258
+ titleEl.textContent = extractTitle(url);
259
+ card.appendChild(titleEl);
260
+
261
+ // URL ๋งํฌ
262
+ const linkEl = document.createElement("a");
263
+ linkEl.href = url;
264
+ linkEl.textContent = url;
265
+ linkEl.target = "_blank";
266
+ card.appendChild(linkEl);
267
+
268
+ // ์ข‹์•„์š” ๋ฒ„ํŠผ (โ™ฅ ์•„์ด์ฝ˜)
269
+ const likeBtn = document.createElement("button");
270
+ likeBtn.className = "like-button";
271
+ likeBtn.textContent = "โ™ฅ";
272
+ if (state.likedUrls[url]) {
273
+ likeBtn.classList.add("liked");
274
+ } else {
275
+ likeBtn.classList.add("not-liked");
276
+ }
277
+ likeBtn.addEventListener("click", function(e) {
278
+ e.preventDefault(); // ๋งํฌ ํด๋ฆญ ๋ฐฉ์ง€
279
+ toggleLike(url, likeBtn);
280
+ });
281
+ card.appendChild(likeBtn);
282
+
283
+ elements.cardsContainer.appendChild(card);
284
+ });
285
+ }
286
+
287
+ // ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์„ค์ •
288
+ elements.loginButton.addEventListener('click', () => {
289
+ login(elements.usernameInput.value);
290
  });
291
+
292
+ elements.logoutButton.addEventListener('click', logout);
293
+
294
+ // ์—”ํ„ฐ ํ‚ค๋กœ ๋กœ๊ทธ์ธ ๊ฐ€๋Šฅํ•˜๊ฒŒ
295
+ elements.usernameInput.addEventListener('keypress', (event) => {
296
+ if (event.key === 'Enter') {
297
+ login(elements.usernameInput.value);
298
+ }
299
+ });
300
+
301
+ // ์ดˆ๊ธฐ ๋ Œ๋”๋ง
302
+ renderCards();
303
  </script>
304
  </body>
305
+ </html>