diff --git a/src/app/saved/saved-mobile.tsx b/src/app/saved/saved-mobile.tsx index c7e40d2..8a35a7e 100644 --- a/src/app/saved/saved-mobile.tsx +++ b/src/app/saved/saved-mobile.tsx @@ -45,6 +45,8 @@ export default function SavedMobile() { const [popupTitle, setPopupTitle] = useState(''); const [selectedTT, setSelectedTT] = useState(null); const [publicToggle, setPublicToggle] = useState(true); + // NEW: for rename support + const [renameValue, setRenameValue] = useState(''); useEffect(() => { if (!userEmail) return; @@ -72,11 +74,29 @@ export default function SavedMobile() { setShowPopup(true); } + // NEW: delete handler (mirrors saved.tsx) + async function handleDelete() { + if (!selectedTT) return; + await axios.delete(`/api/timetables/${selectedTT._id}`); + setTimetables(prev => prev.filter(t => t._id !== selectedTT._id)); + setShowPopup(false); + setSelectedTT(null); + } + + // NEW: rename handler (mirrors saved.tsx) + async function handleRename() { + if (!selectedTT) return; + await axios.patch(`/api/timetables/${selectedTT._id}`, { title: renameValue }); + setTimetables(prev => + prev.map(t => (t._id === selectedTT._id ? { ...t, title: renameValue } : t)) + ); + setShowPopup(false); + setSelectedTT(null); + } + async function handleCopyLink(tt: TimetableEntry) { try { - await axios.patch(`/api/timetables/${tt._id}`, { - isPublic: publicToggle, - }); + await axios.patch(`/api/timetables/${tt._id}`, { isPublic: publicToggle }); const res = await axios.get(`/api/timetables/${tt._id}`); const updated = res.data; if (!updated.shareId) throw new Error('No shareId found'); @@ -88,9 +108,7 @@ export default function SavedMobile() { async function handleTogglePublic(state: 'on' | 'off') { if (!selectedTT) return; setPublicToggle(state === 'on'); - await axios.patch(`/api/timetables/${selectedTT._id}`, { - isPublic: state === 'on', - }); + await axios.patch(`/api/timetables/${selectedTT._id}`, { isPublic: state === 'on' }); setTimetables(prev => prev.map(tt => (tt._id === selectedTT._id ? { ...tt, isPublic: state === 'on' } : tt)) ); @@ -98,6 +116,7 @@ export default function SavedMobile() { return (
+ {/* Background */}
-
Saved Timetables
- -
    - {timetables.map((tt, index) => ( -
  • handleView(tt)} - > - {index + 1}. - {tt.title} -
  • - ))} -
- -
-
- {loading ? null : timetables.length === 0 ? ( - Nothing To Show Here - ) : ( - End of List - )} -
-
+ {/* FIX: reduced mt-28 → mt-20 so title isn't pushed too far down on short phones */} +
Saved Timetables
+ {/* FIX: unified loading/empty/list rendering — no orphaned divider during load */} {loading ? ( - +
+ +
) : timetables.length === 0 ? ( -
- No saved timetables found. -
- Create and save from the desktop website. +
+

+ No saved timetables found. +
+ Create and save from the desktop website. +

- ) : null} + ) : ( + <> +
    + {timetables.map((tt, index) => ( +
  • + {/* Tapping the number or title opens the view popup */} + handleView(tt)} + > + {index + 1}. + + handleView(tt)} + > + {tt.title} + + + {/* NEW: action buttons for rename and delete on mobile */} +
    e.stopPropagation()}> + + +
    +
  • + ))} +
+ + {/* Divider only shown when list is visible */} +
+
+ End of List +
+
+ + )}
+ {/* View popup — unchanged */} {showPopup && popupType === 'view_tt' && selectedTT && ( )} + + {/* NEW: delete confirmation popup */} + {showPopup && popupType === 'delete_tt' && selectedTT && ( +
+
+

+ Delete "{selectedTT.title}"? +

+
+ + +
+
+
+ )} + + {/* NEW: rename popup */} + {showPopup && popupType === 'rename_tt' && selectedTT && ( +
+
+

Rename Timetable

+ setRenameValue(e.target.value)} + /> +
+ + +
+
+
+ )}
); } diff --git a/src/app/slots/slots.tsx b/src/app/slots/slots.tsx index 45c2196..7f58890 100644 --- a/src/app/slots/slots.tsx +++ b/src/app/slots/slots.tsx @@ -180,12 +180,7 @@ export default function View() {
- ({ - slotName: buttonTexts[i], - showName: true, - }))} - /> +