jkushwaha commited on
Commit
efd000b
Β·
verified Β·
1 Parent(s): eca740e

Update a.jsx

Browse files
Files changed (1) hide show
  1. a.jsx +28 -28
a.jsx CHANGED
@@ -1565,7 +1565,7 @@ function CountdownBadge({ remaining, urgent, warning }) {
1565
  }
1566
 
1567
  // ── TestingProfilesPortal ─────────────────────────────────────────────────────
1568
- function TestingProfilesPortal({ currentUser, onEdit, onBack, onLogout }) {
1569
  const [profiles, setProfiles] = useState([]);
1570
  const [loading, setLoading] = useState(true);
1571
  const [deleteTarget, setDeleteTarget] = useState(null);
@@ -1687,7 +1687,7 @@ function TestingProfilesPortal({ currentUser, onEdit, onBack, onLogout }) {
1687
  }
1688
 
1689
  // ── ProfileEditorPortal ───────────────────────────────────────────────────────
1690
- function ProfileEditorPortal({ profile: initialProfile, currentUser, onBack, onLogout }) {
1691
  const [profile, setProfile] = useState(initialProfile);
1692
  const [qs, setQs] = useState(() => initialProfile.questions ?? []);
1693
  const [dirty, setDirty] = useState(false);
@@ -1971,7 +1971,7 @@ function ProfilePickerPortal({ mode, session, onPick, onCancel, onLogout }) {
1971
  }
1972
 
1973
  // ── ProductsPortal ────────────────────────────────────────────────────────────
1974
- function ProductsPortal({ currentUser, onBack, onLogout }) {
1975
  const [products, setProducts] = useState([]);
1976
  const [loading, setLoading] = useState(true);
1977
  const [deleteTarget, setDeleteTarget] = useState(null);
@@ -2116,7 +2116,7 @@ const ROLE_DESC = {
2116
  tester: "Tester portal only β€” upload screenshots per session",
2117
  };
2118
 
2119
- function AccountsPortal({ currentUser, onBack, onLogout }) {
2120
  const [users, setUsers] = useState([]);
2121
  const [allProducts, setAllProducts] = useState([]);
2122
  const [loading, setLoading] = useState(true);
@@ -2519,19 +2519,21 @@ function KanbanPortal({ currentUser, currentRole, onBack, onLogout, onNavigate }
2519
 
2520
  const openEdit = (task) => setModal({ mode: "edit", task: { ...task } });
2521
 
2522
- const handleSave = async (task) => {
2523
  const orig = tasks.find(t => t.id === task.id);
2524
  task.updatedAt = Date.now();
2525
  if (task.label === "daily" && task.status === "backlog") task.status = "in-progress";
2526
- await dbSaveTask(task);
2527
 
2528
- // Close modal and update UI immediately β€” don't wait for notifications
2529
  setTasks(prev => {
2530
  const idx = prev.findIndex(t => t.id === task.id);
2531
  return idx >= 0 ? prev.map(t => t.id === task.id ? task : t) : [...prev, task];
2532
  });
2533
  setModal(null);
2534
 
 
 
 
2535
  // Activity log + notifications fire in background
2536
  const isNew = !orig;
2537
  const changes = [];
@@ -2636,7 +2638,7 @@ function KanbanPortal({ currentUser, currentRole, onBack, onLogout, onNavigate }
2636
  </div>
2637
  <div className="header-right">
2638
  {canCreate && <button className="btn-view-report" onClick={openCreate}>+ New Task</button>}
2639
- <button className="btn-secondary-sm" onClick={() => setShowLog(true)}>πŸ“‹ Log</button>
2640
  <button className="btn-secondary-sm" onClick={onBack}>← Portal</button>
2641
  <NotificationBell username={currentUser} onNavigate={onNavigate} />
2642
  <ProfileMenu username={currentUser} role={currentRole} onLogout={onLogout} />
@@ -2820,12 +2822,10 @@ function TaskModal({ task: initTask, mode, currentUser, currentRole, products, a
2820
  (isTester || task.productId) &&
2821
  (isTester || (task.label === "daily" ? !!task.recurTime : !!task.dueDate));
2822
 
2823
- const handleSubmit = async (e) => {
2824
  e.preventDefault();
2825
  if (!isValid) return;
2826
- setSaving(true);
2827
- await onSave(task);
2828
- setSaving(false);
2829
  };
2830
 
2831
  return (
@@ -2992,8 +2992,8 @@ function TaskModal({ task: initTask, mode, currentUser, currentRole, products, a
2992
 
2993
  <div className="modal-actions" style={{ margin: "16px 28px 24px" }}>
2994
  <button type="button" className="btn-cancel" onClick={onClose}>Cancel</button>
2995
- <button type="submit" className="btn-primary" disabled={saving || !isValid}>
2996
- {saving ? "Saving…" : mode === "create" ? "Create Task" : "Save Changes"}
2997
  </button>
2998
  </div>
2999
  </form>
@@ -3068,18 +3068,20 @@ function TicketsPortal({ currentUser, currentRole, onBack, onLogout, onNavigate
3068
  setModal({ mode: "edit", ticket: { ...ticket } });
3069
  };
3070
 
3071
- const handleSave = async (ticket) => {
3072
  const orig = tickets.find(t => t.id === ticket.id);
3073
  ticket.updatedAt = Date.now();
3074
- await dbSaveTicket(ticket);
3075
 
3076
- // Close modal and update UI immediately β€” don't wait for notifications
3077
  setTickets(prev => {
3078
  const idx = prev.findIndex(t => t.id === ticket.id);
3079
  return idx >= 0 ? prev.map(t => t.id === ticket.id ? ticket : t) : [...prev, ticket];
3080
  });
3081
  setModal(null);
3082
 
 
 
 
3083
  // Activity log + notification fire in background
3084
  const isNew = !orig;
3085
  const changes = [];
@@ -3171,7 +3173,7 @@ function TicketsPortal({ currentUser, currentRole, onBack, onLogout, onNavigate
3171
  <div className="header-left"><h1>Tickets</h1></div>
3172
  <div className="header-right">
3173
  <button className="btn-view-report" onClick={openCreate}>+ New Ticket</button>
3174
- <button className="btn-secondary-sm" onClick={() => setShowLog(true)}>πŸ“‹ Log</button>
3175
  <button className="btn-secondary-sm" onClick={onBack}>← Portal</button>
3176
  <NotificationBell username={currentUser} onNavigate={onNavigate} />
3177
  <ProfileMenu username={currentUser} role={currentRole} onLogout={onLogout} />
@@ -3293,12 +3295,10 @@ function TicketModal({ ticket: initTicket, mode, currentUser, currentRole, produ
3293
  const canAssign = isAdmin || isReviewer;
3294
  const canChangeStatus = isAdmin || isReviewer;
3295
 
3296
- const handleSubmit = async (e) => {
3297
  e.preventDefault();
3298
  if (!ticket.title.trim()) return;
3299
- setSaving(true);
3300
- await onSave(ticket);
3301
- setSaving(false);
3302
  };
3303
 
3304
  return (
@@ -3430,8 +3430,8 @@ function TicketModal({ ticket: initTicket, mode, currentUser, currentRole, produ
3430
 
3431
  <div className="modal-actions" style={{ margin: "16px 28px 24px" }}>
3432
  <button type="button" className="btn-cancel" onClick={onClose}>Cancel</button>
3433
- <button type="submit" className="btn-primary" disabled={saving || !ticket.title.trim()}>
3434
- {saving ? "Saving…" : mode === "create" ? "Create Ticket" : "Save Changes"}
3435
  </button>
3436
  </div>
3437
  </form>
@@ -3908,15 +3908,15 @@ export default function App() {
3908
  if (!session) return <LoginPage onLogin={handleLogin} />;
3909
  if (view === "review") return <ReviewPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3910
  if (view === "reports") return <ReportsPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3911
- if (view === "accounts") return <AccountsPortal currentUser={session.username} onBack={() => setView(null)} onLogout={handleLogout} />;
3912
- if (view === "products") return <ProductsPortal currentUser={session.username} onBack={() => setView(null)} onLogout={handleLogout} />;
3913
  if (view === "planner") return <KanbanPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3914
  if (view === "tickets") return <TicketsPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3915
- if (view === "profiles") return <TestingProfilesPortal currentUser={session.username}
3916
  onEdit={p => { setEditingProfile(p); setView("profile-editor"); }}
3917
  onBack={() => setView(null)} onLogout={handleLogout} />;
3918
  if (view === "profile-editor" && editingProfile) return <ProfileEditorPortal
3919
- profile={editingProfile} currentUser={session.username}
3920
  onBack={() => setView("profiles")} onLogout={handleLogout} />;
3921
  if (session.testingStart && session.testingEnd)
3922
  return <TerminatedScreen session={session} rows={rows}
 
1565
  }
1566
 
1567
  // ── TestingProfilesPortal ─────────────────────────────────────────────────────
1568
+ function TestingProfilesPortal({ currentUser, currentRole, onEdit, onBack, onLogout }) {
1569
  const [profiles, setProfiles] = useState([]);
1570
  const [loading, setLoading] = useState(true);
1571
  const [deleteTarget, setDeleteTarget] = useState(null);
 
1687
  }
1688
 
1689
  // ── ProfileEditorPortal ───────────────────────────────────────────────────────
1690
+ function ProfileEditorPortal({ profile: initialProfile, currentUser, currentRole, onBack, onLogout }) {
1691
  const [profile, setProfile] = useState(initialProfile);
1692
  const [qs, setQs] = useState(() => initialProfile.questions ?? []);
1693
  const [dirty, setDirty] = useState(false);
 
1971
  }
1972
 
1973
  // ── ProductsPortal ────────────────────────────────────────────────────────────
1974
+ function ProductsPortal({ currentUser, currentRole, onBack, onLogout }) {
1975
  const [products, setProducts] = useState([]);
1976
  const [loading, setLoading] = useState(true);
1977
  const [deleteTarget, setDeleteTarget] = useState(null);
 
2116
  tester: "Tester portal only β€” upload screenshots per session",
2117
  };
2118
 
2119
+ function AccountsPortal({ currentUser, currentRole, onBack, onLogout }) {
2120
  const [users, setUsers] = useState([]);
2121
  const [allProducts, setAllProducts] = useState([]);
2122
  const [loading, setLoading] = useState(true);
 
2519
 
2520
  const openEdit = (task) => setModal({ mode: "edit", task: { ...task } });
2521
 
2522
+ const handleSave = (task) => {
2523
  const orig = tasks.find(t => t.id === task.id);
2524
  task.updatedAt = Date.now();
2525
  if (task.label === "daily" && task.status === "backlog") task.status = "in-progress";
 
2526
 
2527
+ // Optimistic update β€” show card and close modal instantly
2528
  setTasks(prev => {
2529
  const idx = prev.findIndex(t => t.id === task.id);
2530
  return idx >= 0 ? prev.map(t => t.id === task.id ? task : t) : [...prev, task];
2531
  });
2532
  setModal(null);
2533
 
2534
+ // Persist to DB in background
2535
+ dbSaveTask(task).catch(() => {});
2536
+
2537
  // Activity log + notifications fire in background
2538
  const isNew = !orig;
2539
  const changes = [];
 
2638
  </div>
2639
  <div className="header-right">
2640
  {canCreate && <button className="btn-view-report" onClick={openCreate}>+ New Task</button>}
2641
+ {isAdmin && <button className="btn-secondary-sm" onClick={() => setShowLog(true)}>πŸ“‹ Log</button>}
2642
  <button className="btn-secondary-sm" onClick={onBack}>← Portal</button>
2643
  <NotificationBell username={currentUser} onNavigate={onNavigate} />
2644
  <ProfileMenu username={currentUser} role={currentRole} onLogout={onLogout} />
 
2822
  (isTester || task.productId) &&
2823
  (isTester || (task.label === "daily" ? !!task.recurTime : !!task.dueDate));
2824
 
2825
+ const handleSubmit = (e) => {
2826
  e.preventDefault();
2827
  if (!isValid) return;
2828
+ onSave(task);
 
 
2829
  };
2830
 
2831
  return (
 
2992
 
2993
  <div className="modal-actions" style={{ margin: "16px 28px 24px" }}>
2994
  <button type="button" className="btn-cancel" onClick={onClose}>Cancel</button>
2995
+ <button type="submit" className="btn-primary" disabled={!isValid}>
2996
+ {mode === "create" ? "Create Task" : "Save Changes"}
2997
  </button>
2998
  </div>
2999
  </form>
 
3068
  setModal({ mode: "edit", ticket: { ...ticket } });
3069
  };
3070
 
3071
+ const handleSave = (ticket) => {
3072
  const orig = tickets.find(t => t.id === ticket.id);
3073
  ticket.updatedAt = Date.now();
 
3074
 
3075
+ // Optimistic update β€” show ticket and close modal instantly
3076
  setTickets(prev => {
3077
  const idx = prev.findIndex(t => t.id === ticket.id);
3078
  return idx >= 0 ? prev.map(t => t.id === ticket.id ? ticket : t) : [...prev, ticket];
3079
  });
3080
  setModal(null);
3081
 
3082
+ // Persist to DB in background
3083
+ dbSaveTicket(ticket).catch(() => {});
3084
+
3085
  // Activity log + notification fire in background
3086
  const isNew = !orig;
3087
  const changes = [];
 
3173
  <div className="header-left"><h1>Tickets</h1></div>
3174
  <div className="header-right">
3175
  <button className="btn-view-report" onClick={openCreate}>+ New Ticket</button>
3176
+ {isAdmin && <button className="btn-secondary-sm" onClick={() => setShowLog(true)}>πŸ“‹ Log</button>}
3177
  <button className="btn-secondary-sm" onClick={onBack}>← Portal</button>
3178
  <NotificationBell username={currentUser} onNavigate={onNavigate} />
3179
  <ProfileMenu username={currentUser} role={currentRole} onLogout={onLogout} />
 
3295
  const canAssign = isAdmin || isReviewer;
3296
  const canChangeStatus = isAdmin || isReviewer;
3297
 
3298
+ const handleSubmit = (e) => {
3299
  e.preventDefault();
3300
  if (!ticket.title.trim()) return;
3301
+ onSave(ticket);
 
 
3302
  };
3303
 
3304
  return (
 
3430
 
3431
  <div className="modal-actions" style={{ margin: "16px 28px 24px" }}>
3432
  <button type="button" className="btn-cancel" onClick={onClose}>Cancel</button>
3433
+ <button type="submit" className="btn-primary" disabled={!ticket.title.trim()}>
3434
+ {mode === "create" ? "Create Ticket" : "Save Changes"}
3435
  </button>
3436
  </div>
3437
  </form>
 
3908
  if (!session) return <LoginPage onLogin={handleLogin} />;
3909
  if (view === "review") return <ReviewPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3910
  if (view === "reports") return <ReportsPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3911
+ if (view === "accounts") return <AccountsPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} />;
3912
+ if (view === "products") return <ProductsPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} />;
3913
  if (view === "planner") return <KanbanPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3914
  if (view === "tickets") return <TicketsPortal currentUser={session.username} currentRole={session.role} onBack={() => setView(null)} onLogout={handleLogout} onNavigate={handleNavigate} />;
3915
+ if (view === "profiles") return <TestingProfilesPortal currentUser={session.username} currentRole={session.role}
3916
  onEdit={p => { setEditingProfile(p); setView("profile-editor"); }}
3917
  onBack={() => setView(null)} onLogout={handleLogout} />;
3918
  if (view === "profile-editor" && editingProfile) return <ProfileEditorPortal
3919
+ profile={editingProfile} currentUser={session.username} currentRole={session.role}
3920
  onBack={() => setView("profiles")} onLogout={handleLogout} />;
3921
  if (session.testingStart && session.testingEnd)
3922
  return <TerminatedScreen session={session} rows={rows}