Taf2023 commited on
Commit
5565235
·
verified ·
1 Parent(s): e02f7fd

Upload 6 files

Browse files
Files changed (6) hide show
  1. __init__.cpython-311.pyc +0 -0
  2. index.html +70 -0
  3. post.cpython-311.pyc +0 -0
  4. script.js +361 -0
  5. style.css +360 -0
  6. user.cpython-311.pyc +0 -0
__init__.cpython-311.pyc ADDED
Binary file (152 Bytes). View file
 
index.html ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="th">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Share YouTube - แชร์วิดีโอและโน๊ตกับเพื่อน</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
9
+ </head>
10
+ <body>
11
+ <div class="container">
12
+ <!-- Header -->
13
+ <header class="header">
14
+ <div class="header-content">
15
+ <h1><i class="fab fa-youtube"></i> Share YouTube</h1>
16
+ <p>แชร์วิดีโอและโน๊ตกับเพื่อน</p>
17
+ </div>
18
+ </header>
19
+
20
+ <!-- Share Form -->
21
+ <div class="share-section">
22
+ <div class="share-card">
23
+ <h2><i class="fas fa-share"></i> แชร์ลิงก์ YouTube</h2>
24
+ <form id="shareForm">
25
+ <div class="form-group">
26
+ <label for="name"><i class="fas fa-user"></i> ชื่อของคุณ:</label>
27
+ <input type="text" id="name" name="name" required placeholder="กรอกชื่อของคุณ">
28
+ </div>
29
+
30
+ <div class="form-group">
31
+ <label for="youtube_link"><i class="fab fa-youtube"></i> ลิงก์ YouTube:</label>
32
+ <input type="url" id="youtube_link" name="youtube_link" required placeholder="https://www.youtube.com/watch?v=...">
33
+ </div>
34
+
35
+ <div class="form-group">
36
+ <label for="note"><i class="fas fa-sticky-note"></i> โน๊ตสั้นๆ:</label>
37
+ <textarea id="note" name="note" required placeholder="เขียนโน๊ตสั้นๆ เกี่ยวกับวิดีโอนี้..."></textarea>
38
+ </div>
39
+
40
+ <button type="submit" class="btn-share">
41
+ <i class="fas fa-share"></i> แชร์
42
+ </button>
43
+ </form>
44
+ </div>
45
+ </div>
46
+
47
+ <!-- Shared Links Feed -->
48
+ <div class="feed-section">
49
+ <h2><i class="fas fa-list"></i> ลิงก์ที่แชร์</h2>
50
+ <div id="linksContainer">
51
+ <!-- Shared links will be loaded here -->
52
+ </div>
53
+ </div>
54
+ </div>
55
+
56
+ <!-- Loading Spinner -->
57
+ <div id="loadingSpinner" class="loading-spinner">
58
+ <i class="fas fa-spinner fa-spin"></i>
59
+ <p>กำลังโหลด...</p>
60
+ </div>
61
+
62
+ <!-- Success Message -->
63
+ <div id="successMessage" class="success-message">
64
+ <i class="fas fa-check-circle"></i>
65
+ <span id="successText">แชร์สำเร็จ!</span>
66
+ </div>
67
+
68
+ <script src="script.js"></script>
69
+ </body>
70
+ </html>
post.cpython-311.pyc ADDED
Binary file (5.01 kB). View file
 
script.js ADDED
@@ -0,0 +1,361 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // API Base URL
2
+ const API_BASE_URL = '/api';
3
+
4
+ // DOM Elements
5
+ const shareForm = document.getElementById('shareForm');
6
+ const linksContainer = document.getElementById('linksContainer');
7
+ const loadingSpinner = document.getElementById('loadingSpinner');
8
+ const successMessage = document.getElementById('successMessage');
9
+ const successText = document.getElementById('successText');
10
+
11
+ // Initialize app
12
+ document.addEventListener('DOMContentLoaded', function() {
13
+ loadLinks();
14
+
15
+ // Handle form submission
16
+ shareForm.addEventListener('submit', handleShareSubmit);
17
+ });
18
+
19
+ // Handle share form submission
20
+ async function handleShareSubmit(e) {
21
+ e.preventDefault();
22
+
23
+ const formData = new FormData(shareForm);
24
+ const data = {
25
+ name: formData.get('name'),
26
+ note: formData.get('note'),
27
+ youtube_link: formData.get('youtube_link')
28
+ };
29
+
30
+ // Validate YouTube URL
31
+ if (!isValidYouTubeURL(data.youtube_link)) {
32
+ alert('กรุณากรอกลิงก์ YouTube ที่ถูกต้อง');
33
+ return;
34
+ }
35
+
36
+ try {
37
+ showLoading(true);
38
+
39
+ const response = await fetch(`${API_BASE_URL}/posts`, {
40
+ method: 'POST',
41
+ headers: {
42
+ 'Content-Type': 'application/json',
43
+ },
44
+ body: JSON.stringify(data)
45
+ });
46
+
47
+ if (!response.ok) {
48
+ throw new Error('เกิดข้อผิดพลาดในการแชร์');
49
+ }
50
+
51
+ const result = await response.json();
52
+
53
+ // Show success message
54
+ showSuccessMessage('แชร์สำเร็จ!');
55
+
56
+ // Clear form
57
+ shareForm.reset();
58
+
59
+ // Reload links
60
+ await loadLinks();
61
+
62
+ } catch (error) {
63
+ console.error('Error sharing link:', error);
64
+ alert('เกิดข้อผิดพลาดในการแชร์: ' + error.message);
65
+ } finally {
66
+ showLoading(false);
67
+ }
68
+ }
69
+
70
+ // Load all shared links
71
+ async function loadLinks() {
72
+ try {
73
+ showLoading(true);
74
+
75
+ const response = await fetch(`${API_BASE_URL}/posts`);
76
+ if (!response.ok) {
77
+ throw new Error('ไม่สามารถโหลดลิงก์ได้');
78
+ }
79
+
80
+ const links = await response.json();
81
+ displayLinks(links);
82
+
83
+ } catch (error) {
84
+ console.error('Error loading links:', error);
85
+ linksContainer.innerHTML = `
86
+ <div style="text-align: center; color: #666; padding: 20px;">
87
+ <i class="fas fa-exclamation-triangle"></i>
88
+ <p>ไม่สามารถโหลดลิงก์ได้: ${error.message}</p>
89
+ </div>
90
+ `;
91
+ } finally {
92
+ showLoading(false);
93
+ }
94
+ }
95
+
96
+ // Display links in the container
97
+ function displayLinks(links) {
98
+ if (links.length === 0) {
99
+ linksContainer.innerHTML = `
100
+ <div style="text-align: center; color: #666; padding: 40px;">
101
+ <i class="fab fa-youtube" style="font-size: 3rem; margin-bottom: 15px;"></i>
102
+ <p>ยังไม่มีลิงก์ที่แชร์</p>
103
+ <p>เป็นคนแรกที่แชร์ลิงก์ YouTube!</p>
104
+ </div>
105
+ `;
106
+ return;
107
+ }
108
+
109
+ linksContainer.innerHTML = links.map(link => createLinkCard(link)).join('');
110
+
111
+ // Add event listeners for like and comment buttons
112
+ addLinkEventListeners();
113
+ }
114
+
115
+ // Create HTML for a single link card
116
+ function createLinkCard(link) {
117
+ const videoId = extractYouTubeVideoId(link.youtube_link);
118
+ const embedUrl = videoId ? `https://www.youtube.com/embed/${videoId}` : '';
119
+ const timeAgo = getTimeAgo(new Date(link.created_at));
120
+
121
+ return `
122
+ <div class="link-card" data-link-id="${link.id}">
123
+ <div class="link-header">
124
+ <span class="user-name">
125
+ <i class="fas fa-user"></i> ${escapeHtml(link.name)}
126
+ </span>
127
+ <span class="timestamp">${timeAgo}</span>
128
+ </div>
129
+
130
+ <div class="link-note">
131
+ ${escapeHtml(link.note)}
132
+ </div>
133
+
134
+ ${embedUrl ? `
135
+ <div class="youtube-embed">
136
+ <iframe src="${embedUrl}"
137
+ title="YouTube video player"
138
+ frameborder="0"
139
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
140
+ allowfullscreen>
141
+ </iframe>
142
+ </div>
143
+ ` : `
144
+ <div class="youtube-link">
145
+ <a href="${link.youtube_link}" target="_blank" rel="noopener noreferrer">
146
+ <i class="fab fa-youtube"></i> ดูวิดีโ���ใน YouTube
147
+ </a>
148
+ </div>
149
+ `}
150
+
151
+ <div class="link-actions">
152
+ <button class="action-btn like-btn" data-link-id="${link.id}">
153
+ <i class="fas fa-heart"></i>
154
+ <span class="like-count">${link.likes}</span>
155
+ </button>
156
+ <button class="action-btn comment-btn" data-link-id="${link.id}">
157
+ <i class="fas fa-comment"></i>
158
+ คอมเมนต์
159
+ </button>
160
+ </div>
161
+
162
+ <div class="comments-section" id="comments-${link.id}" style="display: none;">
163
+ <div class="comment-form">
164
+ <input type="text" placeholder="เขียนคอมเมนต์..." class="comment-input">
165
+ <button type="button" class="add-comment-btn" data-link-id="${link.id}">
166
+ <i class="fas fa-paper-plane"></i>
167
+ </button>
168
+ </div>
169
+ <div class="comments-list" id="comments-list-${link.id}">
170
+ <!-- Comments will be loaded here -->
171
+ </div>
172
+ </div>
173
+ </div>
174
+ `;
175
+ }
176
+
177
+ // Add event listeners for link interactions
178
+ function addLinkEventListeners() {
179
+ // Like buttons
180
+ document.querySelectorAll('.like-btn').forEach(btn => {
181
+ btn.addEventListener('click', handleLike);
182
+ });
183
+
184
+ // Comment buttons
185
+ document.querySelectorAll('.comment-btn').forEach(btn => {
186
+ btn.addEventListener('click', toggleComments);
187
+ });
188
+
189
+ // Add comment buttons
190
+ document.querySelectorAll('.add-comment-btn').forEach(btn => {
191
+ btn.addEventListener('click', handleAddComment);
192
+ });
193
+
194
+ // Enter key for comment input
195
+ document.querySelectorAll('.comment-input').forEach(input => {
196
+ input.addEventListener('keypress', function(e) {
197
+ if (e.key === 'Enter') {
198
+ const linkId = this.closest('.comments-section').id.split('-')[1];
199
+ const btn = document.querySelector(`.add-comment-btn[data-link-id="${linkId}"]`);
200
+ btn.click();
201
+ }
202
+ });
203
+ });
204
+ }
205
+
206
+ // Handle like button click
207
+ async function handleLike(e) {
208
+ const linkId = e.currentTarget.dataset.linkId;
209
+ const likeBtn = e.currentTarget;
210
+ const likeCount = likeBtn.querySelector('.like-count');
211
+
212
+ try {
213
+ const response = await fetch(`${API_BASE_URL}/posts/${linkId}/like`, {
214
+ method: 'POST'
215
+ });
216
+
217
+ if (!response.ok) {
218
+ throw new Error('ไม่สามารถถูกใจได้');
219
+ }
220
+
221
+ const result = await response.json();
222
+ likeCount.textContent = result.likes;
223
+
224
+ // Add visual feedback
225
+ likeBtn.classList.add('liked');
226
+ setTimeout(() => likeBtn.classList.remove('liked'), 1000);
227
+
228
+ } catch (error) {
229
+ console.error('Error liking post:', error);
230
+ alert('เกิดข้อผิดพลาดในการถูกใจ');
231
+ }
232
+ }
233
+
234
+ // Toggle comments section
235
+ async function toggleComments(e) {
236
+ const linkId = e.currentTarget.dataset.linkId;
237
+ const commentsSection = document.getElementById(`comments-${linkId}`);
238
+
239
+ if (commentsSection.style.display === 'none') {
240
+ commentsSection.style.display = 'block';
241
+ await loadComments(linkId);
242
+ } else {
243
+ commentsSection.style.display = 'none';
244
+ }
245
+ }
246
+
247
+ // Load comments for a specific link
248
+ async function loadComments(linkId) {
249
+ try {
250
+ const response = await fetch(`${API_BASE_URL}/posts/${linkId}/comments`);
251
+ if (!response.ok) {
252
+ throw new Error('ไม่สามารถโหลดคอมเมนต์ได้');
253
+ }
254
+
255
+ const comments = await response.json();
256
+ const commentsList = document.getElementById(`comments-list-${linkId}`);
257
+
258
+ if (comments.length === 0) {
259
+ commentsList.innerHTML = '<p style="text-align: center; color: #666; padding: 10px;">ยังไม่มีคอมเมนต์</p>';
260
+ } else {
261
+ commentsList.innerHTML = comments.map(comment => `
262
+ <div class="comment">
263
+ <div class="comment-author">
264
+ <i class="fas fa-user"></i> ${escapeHtml(comment.name)}
265
+ </div>
266
+ <div class="comment-text">${escapeHtml(comment.comment)}</div>
267
+ </div>
268
+ `).join('');
269
+ }
270
+
271
+ } catch (error) {
272
+ console.error('Error loading comments:', error);
273
+ }
274
+ }
275
+
276
+ // Handle add comment
277
+ async function handleAddComment(e) {
278
+ const linkId = e.currentTarget.dataset.linkId;
279
+ const commentsSection = document.getElementById(`comments-${linkId}`);
280
+ const commentInput = commentsSection.querySelector('.comment-input');
281
+ const commentText = commentInput.value.trim();
282
+
283
+ if (!commentText) {
284
+ alert('กรุณาเขียนคอมเมนต์');
285
+ return;
286
+ }
287
+
288
+ // Simple name prompt (in real app, you'd have user authentication)
289
+ const name = prompt('กรุณากรอกชื่อของคุณ:');
290
+ if (!name) return;
291
+
292
+ try {
293
+ const response = await fetch(`${API_BASE_URL}/posts/${linkId}/comments`, {
294
+ method: 'POST',
295
+ headers: {
296
+ 'Content-Type': 'application/json',
297
+ },
298
+ body: JSON.stringify({
299
+ name: name,
300
+ comment: commentText
301
+ })
302
+ });
303
+
304
+ if (!response.ok) {
305
+ throw new Error('ไม่สามารถเพิ่มคอมเมนต์ได้');
306
+ }
307
+
308
+ // Clear input
309
+ commentInput.value = '';
310
+
311
+ // Reload comments
312
+ await loadComments(linkId);
313
+
314
+ showSuccessMessage('เพิ่มคอมเมนต์สำเร็จ!');
315
+
316
+ } catch (error) {
317
+ console.error('Error adding comment:', error);
318
+ alert('เกิดข้อผิดพลาดในการเพิ่มคอมเมนต์');
319
+ }
320
+ }
321
+
322
+ // Utility functions
323
+ function isValidYouTubeURL(url) {
324
+ const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)[a-zA-Z0-9_-]{11}/;
325
+ return youtubeRegex.test(url);
326
+ }
327
+
328
+ function extractYouTubeVideoId(url) {
329
+ const regex = /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/;
330
+ const match = url.match(regex);
331
+ return match ? match[1] : null;
332
+ }
333
+
334
+ function escapeHtml(text) {
335
+ const div = document.createElement('div');
336
+ div.textContent = text;
337
+ return div.innerHTML;
338
+ }
339
+
340
+ function getTimeAgo(date) {
341
+ const now = new Date();
342
+ const diffInSeconds = Math.floor((now - date) / 1000);
343
+
344
+ if (diffInSeconds < 60) return 'เมื่อสักครู่';
345
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)} นาทีที่แล้ว`;
346
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)} ชั่วโมงที่แล้ว`;
347
+ return `${Math.floor(diffInSeconds / 86400)} วันที่แล้ว`;
348
+ }
349
+
350
+ function showLoading(show) {
351
+ loadingSpinner.style.display = show ? 'block' : 'none';
352
+ }
353
+
354
+ function showSuccessMessage(message) {
355
+ successText.textContent = message;
356
+ successMessage.style.display = 'flex';
357
+ setTimeout(() => {
358
+ successMessage.style.display = 'none';
359
+ }, 3000);
360
+ }
361
+
style.css ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
9
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
10
+ min-height: 100vh;
11
+ color: #333;
12
+ }
13
+
14
+ .container {
15
+ max-width: 800px;
16
+ margin: 0 auto;
17
+ padding: 20px;
18
+ }
19
+
20
+ /* Header */
21
+ .header {
22
+ text-align: center;
23
+ margin-bottom: 30px;
24
+ background: rgba(255, 255, 255, 0.95);
25
+ padding: 30px;
26
+ border-radius: 15px;
27
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
28
+ backdrop-filter: blur(10px);
29
+ }
30
+
31
+ .header-content h1 {
32
+ font-size: 2.5rem;
33
+ color: #FF0000;
34
+ margin-bottom: 10px;
35
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
36
+ }
37
+
38
+ .header-content p {
39
+ font-size: 1.1rem;
40
+ color: #666;
41
+ }
42
+
43
+ /* Share Section */
44
+ .share-section {
45
+ margin-bottom: 30px;
46
+ }
47
+
48
+ .share-card {
49
+ background: rgba(255, 255, 255, 0.95);
50
+ padding: 30px;
51
+ border-radius: 15px;
52
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
53
+ backdrop-filter: blur(10px);
54
+ }
55
+
56
+ .share-card h2 {
57
+ color: #333;
58
+ margin-bottom: 25px;
59
+ font-size: 1.5rem;
60
+ text-align: center;
61
+ }
62
+
63
+ .form-group {
64
+ margin-bottom: 20px;
65
+ }
66
+
67
+ .form-group label {
68
+ display: block;
69
+ margin-bottom: 8px;
70
+ font-weight: 600;
71
+ color: #555;
72
+ }
73
+
74
+ .form-group input,
75
+ .form-group textarea {
76
+ width: 100%;
77
+ padding: 12px 15px;
78
+ border: 2px solid #e1e5e9;
79
+ border-radius: 10px;
80
+ font-size: 1rem;
81
+ transition: all 0.3s ease;
82
+ background: rgba(255, 255, 255, 0.9);
83
+ }
84
+
85
+ .form-group input:focus,
86
+ .form-group textarea:focus {
87
+ outline: none;
88
+ border-color: #FF0000;
89
+ box-shadow: 0 0 0 3px rgba(255, 0, 0, 0.1);
90
+ transform: translateY(-2px);
91
+ }
92
+
93
+ .form-group textarea {
94
+ resize: vertical;
95
+ min-height: 80px;
96
+ }
97
+
98
+ .btn-share {
99
+ width: 100%;
100
+ padding: 15px;
101
+ background: linear-gradient(45deg, #FF0000, #CC0000);
102
+ color: white;
103
+ border: none;
104
+ border-radius: 10px;
105
+ font-size: 1.1rem;
106
+ font-weight: 600;
107
+ cursor: pointer;
108
+ transition: all 0.3s ease;
109
+ text-transform: uppercase;
110
+ letter-spacing: 1px;
111
+ }
112
+
113
+ .btn-share:hover {
114
+ transform: translateY(-2px);
115
+ box-shadow: 0 8px 25px rgba(255, 0, 0, 0.3);
116
+ }
117
+
118
+ .btn-share:active {
119
+ transform: translateY(0);
120
+ }
121
+
122
+ /* Feed Section */
123
+ .feed-section {
124
+ background: rgba(255, 255, 255, 0.95);
125
+ padding: 30px;
126
+ border-radius: 15px;
127
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
128
+ backdrop-filter: blur(10px);
129
+ }
130
+
131
+ .feed-section h2 {
132
+ color: #333;
133
+ margin-bottom: 25px;
134
+ font-size: 1.5rem;
135
+ text-align: center;
136
+ }
137
+
138
+ /* Link Card */
139
+ .link-card {
140
+ background: #fff;
141
+ border: 1px solid #e1e5e9;
142
+ border-radius: 12px;
143
+ padding: 20px;
144
+ margin-bottom: 20px;
145
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
146
+ transition: all 0.3s ease;
147
+ }
148
+
149
+ .link-card:hover {
150
+ transform: translateY(-3px);
151
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
152
+ }
153
+
154
+ .link-header {
155
+ display: flex;
156
+ align-items: center;
157
+ margin-bottom: 15px;
158
+ }
159
+
160
+ .link-header .user-name {
161
+ font-weight: 600;
162
+ color: #333;
163
+ margin-right: 10px;
164
+ }
165
+
166
+ .link-header .timestamp {
167
+ color: #888;
168
+ font-size: 0.9rem;
169
+ }
170
+
171
+ .link-note {
172
+ margin-bottom: 15px;
173
+ color: #555;
174
+ line-height: 1.5;
175
+ }
176
+
177
+ .youtube-embed {
178
+ margin-bottom: 15px;
179
+ border-radius: 8px;
180
+ overflow: hidden;
181
+ }
182
+
183
+ .youtube-embed iframe {
184
+ width: 100%;
185
+ height: 315px;
186
+ border: none;
187
+ }
188
+
189
+ .link-actions {
190
+ display: flex;
191
+ gap: 15px;
192
+ padding-top: 15px;
193
+ border-top: 1px solid #e1e5e9;
194
+ }
195
+
196
+ .action-btn {
197
+ background: none;
198
+ border: none;
199
+ padding: 8px 15px;
200
+ border-radius: 20px;
201
+ cursor: pointer;
202
+ transition: all 0.3s ease;
203
+ font-size: 0.9rem;
204
+ display: flex;
205
+ align-items: center;
206
+ gap: 5px;
207
+ }
208
+
209
+ .like-btn {
210
+ color: #666;
211
+ }
212
+
213
+ .like-btn:hover,
214
+ .like-btn.liked {
215
+ background: rgba(255, 0, 0, 0.1);
216
+ color: #FF0000;
217
+ }
218
+
219
+ .comment-btn {
220
+ color: #666;
221
+ }
222
+
223
+ .comment-btn:hover {
224
+ background: rgba(0, 123, 255, 0.1);
225
+ color: #007bff;
226
+ }
227
+
228
+ /* Comments Section */
229
+ .comments-section {
230
+ margin-top: 15px;
231
+ padding-top: 15px;
232
+ border-top: 1px solid #e1e5e9;
233
+ }
234
+
235
+ .comment-form {
236
+ display: flex;
237
+ gap: 10px;
238
+ margin-bottom: 15px;
239
+ }
240
+
241
+ .comment-form input {
242
+ flex: 1;
243
+ padding: 8px 12px;
244
+ border: 1px solid #ddd;
245
+ border-radius: 20px;
246
+ font-size: 0.9rem;
247
+ }
248
+
249
+ .comment-form button {
250
+ padding: 8px 15px;
251
+ background: #007bff;
252
+ color: white;
253
+ border: none;
254
+ border-radius: 20px;
255
+ cursor: pointer;
256
+ font-size: 0.9rem;
257
+ }
258
+
259
+ .comment-form button:hover {
260
+ background: #0056b3;
261
+ }
262
+
263
+ .comment {
264
+ background: #f8f9fa;
265
+ padding: 10px 15px;
266
+ border-radius: 10px;
267
+ margin-bottom: 10px;
268
+ }
269
+
270
+ .comment-author {
271
+ font-weight: 600;
272
+ color: #333;
273
+ margin-bottom: 5px;
274
+ }
275
+
276
+ .comment-text {
277
+ color: #555;
278
+ font-size: 0.9rem;
279
+ }
280
+
281
+ /* Loading Spinner */
282
+ .loading-spinner {
283
+ position: fixed;
284
+ top: 50%;
285
+ left: 50%;
286
+ transform: translate(-50%, -50%);
287
+ background: rgba(255, 255, 255, 0.95);
288
+ padding: 30px;
289
+ border-radius: 15px;
290
+ text-align: center;
291
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
292
+ display: none;
293
+ }
294
+
295
+ .loading-spinner i {
296
+ font-size: 2rem;
297
+ color: #FF0000;
298
+ margin-bottom: 10px;
299
+ }
300
+
301
+ /* Success Message */
302
+ .success-message {
303
+ position: fixed;
304
+ top: 20px;
305
+ right: 20px;
306
+ background: #28a745;
307
+ color: white;
308
+ padding: 15px 20px;
309
+ border-radius: 10px;
310
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
311
+ display: none;
312
+ align-items: center;
313
+ gap: 10px;
314
+ z-index: 1000;
315
+ }
316
+
317
+ .success-message i {
318
+ font-size: 1.2rem;
319
+ }
320
+
321
+ /* Responsive Design */
322
+ @media (max-width: 768px) {
323
+ .container {
324
+ padding: 15px;
325
+ }
326
+
327
+ .header-content h1 {
328
+ font-size: 2rem;
329
+ }
330
+
331
+ .share-card,
332
+ .feed-section {
333
+ padding: 20px;
334
+ }
335
+
336
+ .youtube-embed iframe {
337
+ height: 200px;
338
+ }
339
+
340
+ .link-actions {
341
+ flex-wrap: wrap;
342
+ }
343
+ }
344
+
345
+ /* Animation */
346
+ @keyframes fadeInUp {
347
+ from {
348
+ opacity: 0;
349
+ transform: translateY(30px);
350
+ }
351
+ to {
352
+ opacity: 1;
353
+ transform: translateY(0);
354
+ }
355
+ }
356
+
357
+ .link-card {
358
+ animation: fadeInUp 0.5s ease;
359
+ }
360
+
user.cpython-311.pyc ADDED
Binary file (3.4 kB). View file