Skip to content

Commit d6f5cde

Browse files
authored
Merge pull request #19 from saisri27/sai
feat(ui): demo-polish round — leave/delete, event dates, vibe presets, micro-interactions
2 parents f6f604e + 4c3efb5 commit d6f5cde

7 files changed

Lines changed: 773 additions & 71 deletions

File tree

UI/Plot.html

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,29 @@
2323
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
2424
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700;12..96,800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
2525
<style>
26-
html, body { margin: 0; padding: 0; background: #1E1B4B; min-height: 100vh; }
27-
body { font-family: 'Bricolage Grotesque', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
26+
/* Use dvh on supported browsers (iOS 15.4+, Chrome 108+) so the layout
27+
follows the visible viewport instead of the static one — fixes the
28+
"bottom nav hidden under Safari address bar" problem. */
29+
html, body {
30+
margin: 0; padding: 0;
31+
background: #1E1B4B;
32+
min-height: 100vh;
33+
min-height: 100dvh;
34+
overscroll-behavior-y: none;
35+
}
36+
body {
37+
font-family: 'Bricolage Grotesque', system-ui, sans-serif;
38+
-webkit-font-smoothing: antialiased;
39+
/* Pad for the iOS notch + home-indicator on devices that report safe areas. */
40+
padding-top: env(safe-area-inset-top, 0px);
41+
padding-bottom: env(safe-area-inset-bottom, 0px);
42+
}
2843
* { box-sizing: border-box; }
2944
::-webkit-scrollbar { width: 0; background: transparent; }
3045
button { font-family: inherit; }
46+
/* The fullscreen root container uses 100dvh too so the iOS dynamic
47+
viewport stays consistent — overrides any inline 100vh from app.jsx. */
48+
#root { min-height: 100vh; min-height: 100dvh; }
3149
</style>
3250

3351
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>

UI/api.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,12 @@ window.PLOT_API = (function () {
142142

143143
// ── /groups (multi-user shareable-link sessions) ─────────────────
144144

145-
function createGroup(name, displayName) {
145+
function createGroup(name, displayName, eventDate) {
146146
return call('POST', '/groups', {
147147
name,
148148
creator_user_id: getUserId(),
149149
creator_display_name: displayName || null,
150+
event_date: eventDate || null,
150151
});
151152
}
152153

@@ -161,6 +162,18 @@ window.PLOT_API = (function () {
161162
});
162163
}
163164

165+
function leaveGroup(groupId) {
166+
return call('POST', `/groups/${encodeURIComponent(groupId)}/leave`, {
167+
user_id: getUserId(),
168+
});
169+
}
170+
171+
function deleteGroup(groupId) {
172+
return call('POST', `/groups/${encodeURIComponent(groupId)}/delete`, {
173+
user_id: getUserId(),
174+
});
175+
}
176+
164177
function setGroupPrefs(groupId, prefs) {
165178
return call('POST', `/groups/${encodeURIComponent(groupId)}/prefs`, {
166179
user_id: getUserId(),
@@ -447,6 +460,8 @@ window.PLOT_API = (function () {
447460
createGroup,
448461
peekGroupByToken,
449462
joinGroupAPI,
463+
leaveGroup,
464+
deleteGroup,
450465
setGroupPrefs,
451466
getGroupState,
452467
groupRecommend,

UI/app.jsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,23 @@ function PlotApp() {
284284

285285
// Profile / Home → "leave group" returns to solo mode. We don't delete
286286
// the group server-side (other members keep planning); just clear our
287-
// local context AND any stale per-group state.
288-
function handleLeaveGroup() {
287+
// local context AND any stale per-group state. Best-effort call to the
288+
// backend to delete our group_members row — if the network fails we still
289+
// clear locally so the user isn't stuck staring at a group they wanted
290+
// to leave. They'll re-appear in the list on next refresh if the API
291+
// call didn't actually land, which is the right safety behavior.
292+
async function handleLeaveGroup() {
293+
const gid = currentGroup && currentGroup.id;
289294
_clearGroupSessionState();
290295
setCurrentGroup(null);
291296
setScreen('home');
297+
if (gid) {
298+
try {
299+
await window.PLOT_API.leaveGroup(gid);
300+
} catch (e) {
301+
console.warn('leaveGroup API failed (non-fatal):', e);
302+
}
303+
}
292304
}
293305

294306
// "We went" tap on Group Decision: log the strongest feedback signal
@@ -411,6 +423,15 @@ function PlotApp() {
411423
}}
412424
/>
413425
)}
426+
{/* Global toast notification host. Mounted once at root; any code
427+
can fire toasts via window.plotToast(msg, kind). */}
428+
<ToastHost />
429+
{/* Global confetti host. Mounted at root so window.plotConfetti()
430+
works even when the firing screen navigates away mid-animation. */}
431+
<ConfettiHost />
432+
{/* Global coin-shower host — fires from BudgetChip taps via
433+
window.plotCoinShower(count). Same pattern as ConfettiHost. */}
434+
<CoinShowerHost />
414435
</div>
415436
);
416437

0 commit comments

Comments
 (0)