diff options
| author | Alex Pooley (@zuedev) <zuedev@gmail.com> | 2026-07-25 17:27:38 +0100 |
|---|---|---|
| committer | Alex Pooley (@zuedev) <zuedev@gmail.com> | 2026-07-25 17:27:38 +0100 |
| commit | a85a54651070765d6254287369835d747be1c276 (patch) | |
| tree | 6598d2e36bf5a3770c9450e1acceefcfcb092842 /174bg/manager/src/components/RolePreferences.jsx | |
| parent | 0d001f0094f2784033be52fa2a28102c271ffb1e (diff) | |
| download | unnamed-group-a85a54651070765d6254287369835d747be1c276.tar unnamed-group-a85a54651070765d6254287369835d747be1c276.tar.gz unnamed-group-a85a54651070765d6254287369835d747be1c276.tar.bz2 unnamed-group-a85a54651070765d6254287369835d747be1c276.tar.xz unnamed-group-a85a54651070765d6254287369835d747be1c276.zip | |
manager is now using react
Diffstat (limited to '174bg/manager/src/components/RolePreferences.jsx')
| -rw-r--r-- | 174bg/manager/src/components/RolePreferences.jsx | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/174bg/manager/src/components/RolePreferences.jsx b/174bg/manager/src/components/RolePreferences.jsx new file mode 100644 index 0000000..ab3f282 --- /dev/null +++ b/174bg/manager/src/components/RolePreferences.jsx @@ -0,0 +1,171 @@ +import { Fragment, useState } from "react"; +import { pb } from "../lib/pocketbase"; +import { ROLES } from "../lib/roles"; +import { getOtherJsonData } from "../lib/otherJsonData"; + +export default function RolePreferences({ record, onUpdate }) { + const [editing, setEditing] = useState(false); + const [selected, setSelected] = useState([]); + const [favourite, setFavourite] = useState(null); + const [saving, setSaving] = useState(false); + const [status, setStatus] = useState({ text: "", error: false }); + + const savedPrefs = record?.RolePreferencesSelect ?? []; + const savedFavourite = getOtherJsonData(record).FavouriteRole ?? null; + + function startEdit() { + setSelected(savedPrefs); + setFavourite(savedFavourite); + setEditing(true); + setStatus({ text: "", error: false }); + } + + function cancelEdit() { + setEditing(false); + } + + function toggleRole(value) { + setSelected((prev) => + prev.includes(value) + ? prev.filter((v) => v !== value) + : [...prev, value], + ); + } + + function toggleFavourite(value) { + setFavourite((prev) => (prev === value ? null : value)); + } + + async function save() { + setSaving(true); + try { + const fav = favourite && selected.includes(favourite) ? favourite : null; + const other = getOtherJsonData(record); + if (fav) other.FavouriteRole = fav; + else delete other.FavouriteRole; + + const updated = await pb.collection("members").update(record.id, { + RolePreferencesSelect: selected, + OtherJsonData: other, + }); + onUpdate(updated); + setEditing(false); + setStatus({ text: "", error: false }); + } catch (err) { + const msg = err?.response + ? JSON.stringify(err.response) + : (err?.message ?? String(err)); + setStatus({ text: `Save failed: ${msg}`, error: true }); + } finally { + setSaving(false); + } + } + + const displayPrefs = editing ? selected : savedPrefs; + const displayFavourite = editing ? favourite : savedFavourite; + + let lastBranch = null; + + return ( + <div id="preferences"> + <div> + <b>Role Preferences</b>{" "} + {!editing && ( + <button type="button" onClick={startEdit}> + ✏️ Edit + </button> + )} + {editing && ( + <> + <button type="button" disabled={saving} onClick={save}> + 💾 Save + </button>{" "} + <button type="button" disabled={saving} onClick={cancelEdit}> + ❌ Cancel + </button> + </> + )} + </div> + <table> + <thead> + <tr> + <th>Role</th> + <th>✅</th> + <th>⭐</th> + </tr> + </thead> + <tbody> + {ROLES.map((role) => { + const branchHeader = role.branch !== lastBranch; + lastBranch = role.branch; + return ( + <Fragment key={role.value}> + {branchHeader && ( + <tr data-separator="true"> + <td + colSpan={3} + style={{ + fontWeight: 600, + paddingTop: "0.75rem", + paddingBottom: "0.25rem", + borderBottom: "none", + opacity: 0.6, + fontSize: "0.8rem", + textTransform: "uppercase", + letterSpacing: "0.05em", + }} + > + {role.branch ?? ""} + </td> + </tr> + )} + <tr> + <td> + {role.link ? ( + <a href={role.link} target="_blank" rel="noopener noreferrer"> + {role.text} + </a> + ) : ( + role.text + )} + </td> + <td> + {editing ? ( + <input + type="checkbox" + checked={selected.includes(role.value)} + onChange={() => toggleRole(role.value)} + /> + ) : displayPrefs.includes(role.value) ? ( + "✅" + ) : ( + "❌" + )} + </td> + <td> + {editing ? ( + <input + type="radio" + name="favourite-role" + checked={favourite === role.value} + onChange={() => {}} + onClick={() => toggleFavourite(role.value)} + /> + ) : displayFavourite === role.value ? ( + "⭐" + ) : ( + "" + )} + </td> + </tr> + </Fragment> + ); + })} + </tbody> + </table> + <p style={{ margin: 0, fontSize: "0.85rem", color: status.error ? "red" : "" }}> + {status.text} + </p> + </div> + ); +} |
