MrNoOne07 commited on
Commit
dccd9d7
Β·
verified Β·
1 Parent(s): cebc572

Add connection deletion actions

Browse files
Files changed (4) hide show
  1. app.py +36 -12
  2. database.py +17 -8
  3. templates/hospital.html +25 -1
  4. templates/patient.html +26 -2
app.py CHANGED
@@ -560,22 +560,46 @@ def get_hospital_connections():
560
  return jsonify({"connections": db.get_hospital_connections(session["hospital_id"])})
561
 
562
 
563
- @app.route("/api/hospital/connections/<cid>/status", methods=["PUT"])
564
- def update_hospital_connection_status(cid):
565
- err = _hospital_required()
566
- if err:
567
- return err
568
  data = request.get_json(force=True) or {}
569
  status = data.get("status", "")
570
  if status not in ("pending", "accepted", "rejected", "completed"):
571
  return jsonify({"error": "Invalid status"}), 400
572
- db.update_connection_status(cid, status)
573
- return jsonify({"success": True})
574
-
575
-
576
- # ---------------------------------------------------------------------------
577
- # Connection Messages
578
- # ---------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
 
580
  @app.route("/api/patient/connections/<cid>/messages", methods=["GET"])
581
  def get_patient_connection_messages(cid):
 
560
  return jsonify({"connections": db.get_hospital_connections(session["hospital_id"])})
561
 
562
 
563
+ @app.route("/api/hospital/connections/<cid>/status", methods=["PUT"])
564
+ def update_hospital_connection_status(cid):
565
+ err = _hospital_required()
566
+ if err:
567
+ return err
568
  data = request.get_json(force=True) or {}
569
  status = data.get("status", "")
570
  if status not in ("pending", "accepted", "rejected", "completed"):
571
  return jsonify({"error": "Invalid status"}), 400
572
+ db.update_connection_status(cid, status)
573
+ return jsonify({"success": True})
574
+
575
+
576
+ @app.route("/api/patient/connections/<cid>", methods=["DELETE"])
577
+ def delete_patient_connection(cid):
578
+ err = _patient_required()
579
+ if err:
580
+ return err
581
+ conn = db.get_connection(cid)
582
+ if not conn or conn["patient_id"] != session["patient_id"]:
583
+ return jsonify({"error": "Not found"}), 404
584
+ db.delete_connection(cid)
585
+ return jsonify({"success": True})
586
+
587
+
588
+ @app.route("/api/hospital/connections/<cid>", methods=["DELETE"])
589
+ def delete_hospital_connection(cid):
590
+ err = _hospital_required()
591
+ if err:
592
+ return err
593
+ conn = db.get_connection(cid)
594
+ if not conn or conn["hospital_id"] != session["hospital_id"]:
595
+ return jsonify({"error": "Not found"}), 404
596
+ db.delete_connection(cid)
597
+ return jsonify({"success": True})
598
+
599
+
600
+ # ---------------------------------------------------------------------------
601
+ # Connection Messages
602
+ # ---------------------------------------------------------------------------
603
 
604
  @app.route("/api/patient/connections/<cid>/messages", methods=["GET"])
605
  def get_patient_connection_messages(cid):
database.py CHANGED
@@ -559,14 +559,23 @@ def get_hospital_connections(hospital_id: str) -> list:
559
  return result
560
 
561
 
562
- def update_connection_status(cid: str, status: str):
563
- with _conn() as c:
564
- c.execute("UPDATE connections SET status=? WHERE id=?", (status, cid))
565
- c.commit()
566
-
567
-
568
- def get_open_patients_for_hospital(hospital_id: str, condition_filter: str = "",
569
- include_connected: bool = False) -> list:
 
 
 
 
 
 
 
 
 
570
  """
571
  Returns patients who are open_to_trials=1, optionally filtered by condition.
572
  When include_connected=False (default), excludes patients already connected to this hospital.
 
559
  return result
560
 
561
 
562
+ def update_connection_status(cid: str, status: str):
563
+ with _conn() as c:
564
+ c.execute("UPDATE connections SET status=? WHERE id=?", (status, cid))
565
+ c.commit()
566
+
567
+
568
+ def delete_connection(cid: str) -> bool:
569
+ """Delete a connection and its message history."""
570
+ with _conn() as c:
571
+ c.execute("DELETE FROM connection_messages WHERE connection_id=?", (cid,))
572
+ cur = c.execute("DELETE FROM connections WHERE id=?", (cid,))
573
+ c.commit()
574
+ return cur.rowcount > 0
575
+
576
+
577
+ def get_open_patients_for_hospital(hospital_id: str, condition_filter: str = "",
578
+ include_connected: bool = False) -> list:
579
  """
580
  Returns patients who are open_to_trials=1, optionally filtered by condition.
581
  When include_connected=False (default), excludes patients already connected to this hospital.
templates/hospital.html CHANGED
@@ -163,7 +163,7 @@ body{background:#0d1117;}
163
  <table class="table table-dark table-hover table-sm align-middle">
164
  <thead><tr>
165
  <th>Patient</th><th>Age/Gender</th><th>Conditions</th>
166
- <th>Trial</th><th>Initiated</th><th>Status</th><th>Message</th><th>Action</th><th>Chat</th>
167
  </tr></thead>
168
  <tbody id="cTbody"></tbody>
169
  </table>
@@ -264,6 +264,7 @@ document.addEventListener('DOMContentLoaded', () => {
264
  if (!btn) return;
265
  if (btn.dataset.st) updateStatus(btn.dataset.cid, btn.dataset.st);
266
  else if ('chat' in btn.dataset) openMsgModal(btn.dataset.cid, btn.dataset.chat);
 
267
  });
268
 
269
  loadPatients();
@@ -451,6 +452,15 @@ async function loadConnections() {
451
  `<button class="btn btn-sm btn-outline-info py-0 px-2" style="font-size:.72rem"
452
  data-cid="${escA(c.id)}" data-chat="${escA(pname)}">πŸ’¬ Chat</button>`,
453
  ].map(v=>`<td>${v}</td>`).join('');
 
 
 
 
 
 
 
 
 
454
  tbody.appendChild(tr);
455
  });
456
  } catch(e) {}
@@ -477,6 +487,20 @@ async function updateStatus(cid, status) {
477
  }
478
 
479
  // ── MY TRIALS ────────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  async function loadTrials() {
481
  show('tLoading'); hide('tEmpty'); document.getElementById('tGrid').innerHTML = '';
482
  try {
 
163
  <table class="table table-dark table-hover table-sm align-middle">
164
  <thead><tr>
165
  <th>Patient</th><th>Age/Gender</th><th>Conditions</th>
166
+ <th>Trial</th><th>Initiated</th><th>Status</th><th>Message</th><th>Status Action</th><th>Actions</th>
167
  </tr></thead>
168
  <tbody id="cTbody"></tbody>
169
  </table>
 
264
  if (!btn) return;
265
  if (btn.dataset.st) updateStatus(btn.dataset.cid, btn.dataset.st);
266
  else if ('chat' in btn.dataset) openMsgModal(btn.dataset.cid, btn.dataset.chat);
267
+ else if ('del' in btn.dataset) deleteConnection(btn.dataset.cid, btn.dataset.del);
268
  });
269
 
270
  loadPatients();
 
452
  `<button class="btn btn-sm btn-outline-info py-0 px-2" style="font-size:.72rem"
453
  data-cid="${escA(c.id)}" data-chat="${escA(pname)}">πŸ’¬ Chat</button>`,
454
  ].map(v=>`<td>${v}</td>`).join('');
455
+ const actionsCell = tr.lastElementChild;
456
+ const delBtn = document.createElement('button');
457
+ delBtn.type = 'button';
458
+ delBtn.className = 'btn btn-sm btn-outline-danger py-0 px-2 ms-1';
459
+ delBtn.style.fontSize = '.72rem';
460
+ delBtn.textContent = 'Delete';
461
+ delBtn.dataset.cid = c.id;
462
+ delBtn.dataset.del = pname;
463
+ actionsCell.appendChild(delBtn);
464
  tbody.appendChild(tr);
465
  });
466
  } catch(e) {}
 
487
  }
488
 
489
  // ── MY TRIALS ────────────────────────────────────────────────────────────────
490
+ async function deleteConnection(cid, patientName) {
491
+ const ok = confirm(`Remove connection with ${patientName || 'this patient'}? This will also remove the chat thread.`);
492
+ if (!ok) return;
493
+ try {
494
+ const r = await fetch('/api/hospital/connections/'+encodeURIComponent(cid), {method:'DELETE'});
495
+ const d = await r.json();
496
+ if (!r.ok) { alert(d.error || 'Delete failed'); return; }
497
+ await loadConnections();
498
+ loadInbox();
499
+ } catch(e) {
500
+ alert('Network error');
501
+ }
502
+ }
503
+
504
  async function loadTrials() {
505
  show('tLoading'); hide('tEmpty'); document.getElementById('tGrid').innerHTML = '';
506
  try {
templates/patient.html CHANGED
@@ -192,7 +192,7 @@ body{background:#0d1117;}
192
  <table class="table table-dark table-hover table-sm align-middle">
193
  <thead><tr>
194
  <th>Hospital</th><th>Trial</th><th>Initiated By</th>
195
- <th>Status</th><th>Message</th><th>Date</th><th>Chat</th>
196
  </tr></thead>
197
  <tbody id="connsTbody"></tbody>
198
  </table>
@@ -678,12 +678,36 @@ async function loadConnections() {
678
  `<button class="btn btn-sm btn-outline-info py-0 px-2" style="font-size:.72rem"
679
  onclick="openMsgModal('${escA(c.id)}','${escA(hname)}')">πŸ’¬ Chat</button>`,
680
  ].map(v=>`<td>${v}</td>`).join('');
 
 
 
 
 
 
 
 
681
  tbody.appendChild(tr);
682
  });
683
  } catch(e) {}
684
  }
685
 
686
- // ── DOCUMENTS ─────────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
687
  function renderDocList() {
688
  const wrap = document.getElementById('docList');
689
  wrap.innerHTML = '';
 
192
  <table class="table table-dark table-hover table-sm align-middle">
193
  <thead><tr>
194
  <th>Hospital</th><th>Trial</th><th>Initiated By</th>
195
+ <th>Status</th><th>Message</th><th>Date</th><th>Actions</th>
196
  </tr></thead>
197
  <tbody id="connsTbody"></tbody>
198
  </table>
 
678
  `<button class="btn btn-sm btn-outline-info py-0 px-2" style="font-size:.72rem"
679
  onclick="openMsgModal('${escA(c.id)}','${escA(hname)}')">πŸ’¬ Chat</button>`,
680
  ].map(v=>`<td>${v}</td>`).join('');
681
+ const actionsCell = tr.lastElementChild;
682
+ const delBtn = document.createElement('button');
683
+ delBtn.type = 'button';
684
+ delBtn.className = 'btn btn-sm btn-outline-danger py-0 px-2 ms-1';
685
+ delBtn.style.fontSize = '.72rem';
686
+ delBtn.textContent = 'Delete';
687
+ delBtn.addEventListener('click', () => deleteConnection(c.id, hname));
688
+ actionsCell.appendChild(delBtn);
689
  tbody.appendChild(tr);
690
  });
691
  } catch(e) {}
692
  }
693
 
694
+ // Connection removal
695
+ // Remove the selected hospital connection and associated chat thread.
696
+ async function deleteConnection(cid, hospitalName) {
697
+ const ok = confirm(`Remove connection with ${hospitalName || 'this hospital'}? This will also remove the chat thread.`);
698
+ if (!ok) return;
699
+ try {
700
+ const r = await fetch('/api/patient/connections/'+encodeURIComponent(cid), {method:'DELETE'});
701
+ const d = await r.json();
702
+ if (!r.ok) { alert(d.error || 'Delete failed'); return; }
703
+ await loadConnections();
704
+ loadInbox();
705
+ } catch(e) {
706
+ alert('Network error');
707
+ }
708
+ }
709
+
710
+ // Documents
711
  function renderDocList() {
712
  const wrap = document.getElementById('docList');
713
  wrap.innerHTML = '';