privateuserh commited on
Commit
d547a7b
·
verified ·
1 Parent(s): dd791b8

Update scripts/ui.js

Browse files
Files changed (1) hide show
  1. scripts/ui.js +41 -23
scripts/ui.js CHANGED
@@ -1,4 +1,4 @@
1
- // scripts/ui.js -- Final version with form handling
2
 
3
  const BACKEND_URL = 'https://stream-ai-backend.smplushypermedia.workers.dev';
4
 
@@ -8,17 +8,27 @@ const getElement = (id) => document.getElementById(id);
8
  function showNotification(message, isError = false) {
9
  const container = getElement('notification');
10
  if (!container) return;
11
-
12
  const bgColor = isError ? 'bg-red-500' : 'bg-green-500';
13
  container.innerHTML = `<div class="flex items-center text-white p-4 rounded-lg shadow-lg ${bgColor}"><i class="fas fa-check-circle mr-3"></i><p>${message}</p></div>`;
14
-
15
  container.classList.add('show');
16
  setTimeout(() => { container.classList.remove('show'); }, 4000);
17
  }
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
- // --- Core Functions ---
21
-
22
  async function loadRecommendations() {
23
  const container = getElement('recommendations-container');
24
  if (!container) return;
@@ -26,30 +36,25 @@ async function loadRecommendations() {
26
  const response = await fetch(`${BACKEND_URL}/api/recommendations`);
27
  if (!response.ok) throw new Error(`Network Error: ${response.statusText}`);
28
  const listings = await response.json();
29
- container.innerHTML = ''; // Clear before loading
30
  if (listings.length === 0) {
31
  container.innerHTML = `<p class="text-center col-span-full text-gray-500">No recommendations available yet.</p>`;
32
  return;
33
  }
34
- listings.forEach(item => {
35
- const card = document.createElement('div');
36
- // ... (The card rendering logic from the previous step remains the same) ...
37
- container.appendChild(card);
38
- });
39
  } catch (error) {
40
  container.innerHTML = `<p class="text-center col-span-full text-red-500">Could not load recommendations.</p>`;
41
  }
42
  }
43
 
44
  async function handleFormSubmit(event) {
45
- event.preventDefault(); // Stop the browser from reloading the page
46
  const form = event.target;
47
  const submitButton = getElement('submit-listing-btn');
48
  submitButton.disabled = true;
49
  submitButton.textContent = 'Submitting...';
50
 
51
- const formData = new FormData(form);
52
- const listingData = Object.fromEntries(formData.entries());
53
 
54
  try {
55
  const response = await fetch(`${BACKEND_URL}/api/add-listing`, {
@@ -57,16 +62,21 @@ async function handleFormSubmit(event) {
57
  headers: { 'Content-Type': 'application/json' },
58
  body: JSON.stringify(listingData),
59
  });
60
-
61
  const result = await response.json();
62
-
63
- if (!response.ok) {
64
- throw new Error(result.details || 'Submission failed.');
65
- }
66
 
67
  showNotification('Success! Your recommendation has been added.');
68
- form.reset(); // Clear the form fields
69
- loadRecommendations(); // Refresh the list to show the new item
 
 
 
 
 
 
 
 
 
70
 
71
  } catch (error) {
72
  showNotification(`Error: ${error.message}`, true);
@@ -77,14 +87,22 @@ async function handleFormSubmit(event) {
77
  }
78
 
79
  // --- Initialization ---
80
-
81
  export function initUI() {
82
  const addListingForm = getElement('add-listing-form');
 
 
 
 
 
 
 
 
 
 
83
 
84
  if (addListingForm) {
85
  addListingForm.addEventListener('submit', handleFormSubmit);
86
  }
87
 
88
- // Load the initial recommendations when the page loads
89
  loadRecommendations();
90
  }
 
1
+ // scripts/ui.js -- Final version with dropdown form and instant UI update
2
 
3
  const BACKEND_URL = 'https://stream-ai-backend.smplushypermedia.workers.dev';
4
 
 
8
  function showNotification(message, isError = false) {
9
  const container = getElement('notification');
10
  if (!container) return;
 
11
  const bgColor = isError ? 'bg-red-500' : 'bg-green-500';
12
  container.innerHTML = `<div class="flex items-center text-white p-4 rounded-lg shadow-lg ${bgColor}"><i class="fas fa-check-circle mr-3"></i><p>${message}</p></div>`;
 
13
  container.classList.add('show');
14
  setTimeout(() => { container.classList.remove('show'); }, 4000);
15
  }
16
 
17
+ // --- Card Rendering ---
18
+ function createListingCard(item) {
19
+ const card = document.createElement('div');
20
+ const pinnedClass = item.is_pinned ? 'border-2 border-indigo-400' : 'shadow-md';
21
+ card.className = `stream-card bg-white rounded-lg overflow-hidden hover:shadow-xl transition duration-300 p-4 relative ${pinnedClass}`;
22
+ card.innerHTML = `
23
+ ${item.is_pinned ? '<div class="absolute top-2 right-2 text-xs bg-indigo-500 text-white px-2 py-1 rounded-full animate-pulse"><i class="fas fa-thumbtack mr-1"></i> Pinned</div>' : ''}
24
+ <div class="mb-3"><h3 class="font-bold text-base">${item.title}</h3><div class="text-xs text-gray-500 mb-2 mt-1">From: <span class="font-semibold text-indigo-600">${item.source_name}</span></div></div>
25
+ <p class="text-gray-700 text-sm mb-4">${item.description || ''}</p>
26
+ <div class="flex justify-between items-center mt-auto"><span class="text-xs font-bold uppercase text-gray-400">${(item.category || '').replace('_', ' ')}</span><a href="${item.url}" target="_blank" rel="noopener noreferrer" class="bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1 rounded-full text-xs font-medium transition">Visit Site</a></div>
27
+ `;
28
+ return card;
29
+ }
30
 
31
+ // --- Core Logic ---
 
32
  async function loadRecommendations() {
33
  const container = getElement('recommendations-container');
34
  if (!container) return;
 
36
  const response = await fetch(`${BACKEND_URL}/api/recommendations`);
37
  if (!response.ok) throw new Error(`Network Error: ${response.statusText}`);
38
  const listings = await response.json();
39
+ container.innerHTML = '';
40
  if (listings.length === 0) {
41
  container.innerHTML = `<p class="text-center col-span-full text-gray-500">No recommendations available yet.</p>`;
42
  return;
43
  }
44
+ listings.forEach(item => container.appendChild(createListingCard(item)));
 
 
 
 
45
  } catch (error) {
46
  container.innerHTML = `<p class="text-center col-span-full text-red-500">Could not load recommendations.</p>`;
47
  }
48
  }
49
 
50
  async function handleFormSubmit(event) {
51
+ event.preventDefault();
52
  const form = event.target;
53
  const submitButton = getElement('submit-listing-btn');
54
  submitButton.disabled = true;
55
  submitButton.textContent = 'Submitting...';
56
 
57
+ const listingData = Object.fromEntries(new FormData(form).entries());
 
58
 
59
  try {
60
  const response = await fetch(`${BACKEND_URL}/api/add-listing`, {
 
62
  headers: { 'Content-Type': 'application/json' },
63
  body: JSON.stringify(listingData),
64
  });
 
65
  const result = await response.json();
66
+ if (!response.ok) throw new Error(result.details || 'Submission failed.');
 
 
 
67
 
68
  showNotification('Success! Your recommendation has been added.');
69
+
70
+ // --- BUG FIX: INSTANT UI UPDATE ---
71
+ // 1. Create a new card with the data we just submitted.
72
+ const newCard = createListingCard(listingData);
73
+ // 2. Add it to the top of the list for an instant refresh.
74
+ getElement('recommendations-container').prepend(newCard);
75
+ // 3. Close the form.
76
+ getElement('form-container').classList.add('hidden');
77
+ getElement('form-chevron').classList.remove('rotate-180');
78
+
79
+ form.reset();
80
 
81
  } catch (error) {
82
  showNotification(`Error: ${error.message}`, true);
 
87
  }
88
 
89
  // --- Initialization ---
 
90
  export function initUI() {
91
  const addListingForm = getElement('add-listing-form');
92
+ const toggleBtn = getElement('toggle-form-btn');
93
+ const formContainer = getElement('form-container');
94
+ const chevron = getElement('form-chevron');
95
+
96
+ if (toggleBtn && formContainer && chevron) {
97
+ toggleBtn.addEventListener('click', () => {
98
+ formContainer.classList.toggle('hidden');
99
+ chevron.classList.toggle('rotate-180');
100
+ });
101
+ }
102
 
103
  if (addListingForm) {
104
  addListingForm.addEventListener('submit', handleFormSubmit);
105
  }
106
 
 
107
  loadRecommendations();
108
  }