Refresh org portal state and treasury interactions
- Hydrate portal/session data from login and sync payloads - Add treasury notices for credit, invite, leave, and disband actions - Improve portal cards and modal UI for members, fleet, and treasury
This commit is contained in:
parent
8a31d456f1
commit
d8812df381
File diff suppressed because one or more lines are too long
@ -25,16 +25,16 @@ ${scopeSelector} .org-members-head {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
${scopeSelector} .org-members-section {
|
${scopeSelector} .org-members-copy {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.85rem;
|
gap: 0.35rem;
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
${scopeSelector} .org-members-section h4 {
|
${scopeSelector} .org-members-kicker {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
@ -42,6 +42,84 @@ ${scopeSelector} .org-members-section h4 {
|
|||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-members-subtitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-members-tools {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-tool-btn {
|
||||||
|
position: relative;
|
||||||
|
width: 2.4rem;
|
||||||
|
height: 2.4rem;
|
||||||
|
padding: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-tool-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: -0.25rem;
|
||||||
|
right: -0.25rem;
|
||||||
|
min-width: 1.1rem;
|
||||||
|
height: 1.1rem;
|
||||||
|
padding: 0 0.2rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #b91c1c;
|
||||||
|
color: white;
|
||||||
|
font-size: 0.68rem;
|
||||||
|
font-weight: 700;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-invite-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 0.5rem);
|
||||||
|
right: 0;
|
||||||
|
width: min(24rem, 100%);
|
||||||
|
max-height: 22rem;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 18px 45px rgb(15 23 42 / 0.18);
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-invite-menu-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-invite-menu-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-invite-menu-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-invite-row,
|
||||||
${scopeSelector} .org-name-row {
|
${scopeSelector} .org-name-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -73,7 +151,8 @@ ${scopeSelector} .org-name-meta {
|
|||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
${scopeSelector} .org-inline-actions {
|
${scopeSelector} .org-inline-actions,
|
||||||
|
${scopeSelector} .org-invite-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
@ -92,13 +171,25 @@ ${scopeSelector} .org-members-empty {
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
${scopeSelector} .org-name-row {
|
${scopeSelector} .org-members-tools {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-invite-menu {
|
||||||
|
left: 0;
|
||||||
|
right: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
${scopeSelector} .org-name-row,
|
||||||
|
${scopeSelector} .org-invite-row {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
${scopeSelector} .org-name-row button,
|
${scopeSelector} .org-name-row button,
|
||||||
${scopeSelector} .org-inline-actions {
|
${scopeSelector} .org-inline-actions,
|
||||||
|
${scopeSelector} .org-invite-actions {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,6 +201,7 @@ ${scopeSelector} .org-members-empty {
|
|||||||
const PanelCard = window.SharedUI.componentFns.PanelCard;
|
const PanelCard = window.SharedUI.componentFns.PanelCard;
|
||||||
const members = store.getMembers();
|
const members = store.getMembers();
|
||||||
const pendingInvites = store.getPendingInvites();
|
const pendingInvites = store.getPendingInvites();
|
||||||
|
const inviteMenuOpen = store.getInviteMenuOpen();
|
||||||
const allowMemberManagement = getters.canManageMembers();
|
const allowMemberManagement = getters.canManageMembers();
|
||||||
ensureScopedStyle("portal-members-card", membersCardCss);
|
ensureScopedStyle("portal-members-card", membersCardCss);
|
||||||
|
|
||||||
@ -127,80 +219,211 @@ ${scopeSelector} .org-members-empty {
|
|||||||
{ className: "org-members-head" },
|
{ className: "org-members-head" },
|
||||||
h(
|
h(
|
||||||
"div",
|
"div",
|
||||||
{ className: "org-members-section" },
|
{ className: "org-members-copy" },
|
||||||
h("h4", null, "Pending Invites"),
|
h("h4", { className: "org-members-kicker" }, "Roster"),
|
||||||
pendingInvites.length === 0
|
h(
|
||||||
|
"p",
|
||||||
|
{ className: "org-members-subtitle" },
|
||||||
|
"Manage membership and review incoming organization invites.",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
"div",
|
||||||
|
{ className: "org-members-tools" },
|
||||||
|
h(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
className:
|
||||||
|
"org-secondary-btn org-icon-btn org-tool-btn",
|
||||||
|
title: "Pending invitations",
|
||||||
|
"aria-label": "Pending invitations",
|
||||||
|
onClick: () => actions.toggleInviteMenu(),
|
||||||
|
},
|
||||||
|
h(
|
||||||
|
"svg",
|
||||||
|
{
|
||||||
|
className: "org-icon",
|
||||||
|
viewBox: "0 0 24 24",
|
||||||
|
fill: "none",
|
||||||
|
stroke: "currentColor",
|
||||||
|
"stroke-width": "2",
|
||||||
|
"stroke-linecap": "round",
|
||||||
|
"stroke-linejoin": "round",
|
||||||
|
"aria-hidden": "true",
|
||||||
|
},
|
||||||
|
h("path", {
|
||||||
|
d: "M15 17h5l-1.4-1.4A2 2 0 0 1 18 14.2V11a6 6 0 1 0-12 0v3.2a2 2 0 0 1-.6 1.4L4 17h5",
|
||||||
|
}),
|
||||||
|
h("path", { d: "M9.73 21a2 2 0 0 0 4.54 0" }),
|
||||||
|
),
|
||||||
|
pendingInvites.length > 0
|
||||||
|
? h(
|
||||||
|
"span",
|
||||||
|
{ className: "org-tool-badge" },
|
||||||
|
String(pendingInvites.length),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
allowMemberManagement
|
||||||
? h(
|
? h(
|
||||||
"p",
|
"button",
|
||||||
{ className: "org-members-empty" },
|
{
|
||||||
"No incoming organization invites.",
|
type: "button",
|
||||||
|
className:
|
||||||
|
"org-secondary-btn org-icon-btn org-tool-btn",
|
||||||
|
title: "Invite player",
|
||||||
|
"aria-label": "Invite player",
|
||||||
|
onClick: () =>
|
||||||
|
actions.openModal("invite"),
|
||||||
|
},
|
||||||
|
h(
|
||||||
|
"svg",
|
||||||
|
{
|
||||||
|
className: "org-icon",
|
||||||
|
viewBox: "0 0 24 24",
|
||||||
|
fill: "none",
|
||||||
|
stroke: "currentColor",
|
||||||
|
"stroke-width": "2",
|
||||||
|
"stroke-linecap": "round",
|
||||||
|
"stroke-linejoin": "round",
|
||||||
|
"aria-hidden": "true",
|
||||||
|
},
|
||||||
|
h("path", { d: "M12 5v14" }),
|
||||||
|
h("path", { d: "M5 12h14" }),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
inviteMenuOpen
|
||||||
|
? h(
|
||||||
|
"div",
|
||||||
|
{ className: "org-invite-menu" },
|
||||||
|
h(
|
||||||
|
"div",
|
||||||
|
{ className: "org-invite-menu-head" },
|
||||||
|
h(
|
||||||
|
"h4",
|
||||||
|
{
|
||||||
|
className:
|
||||||
|
"org-invite-menu-title",
|
||||||
|
},
|
||||||
|
"Pending Invites",
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
className:
|
||||||
|
"org-secondary-btn org-icon-btn org-tool-btn",
|
||||||
|
title: "Close invites",
|
||||||
|
"aria-label": "Close invites",
|
||||||
|
onClick: () =>
|
||||||
|
actions.closeInviteMenu(),
|
||||||
|
},
|
||||||
|
h(
|
||||||
|
"svg",
|
||||||
|
{
|
||||||
|
className: "org-icon",
|
||||||
|
viewBox: "0 0 24 24",
|
||||||
|
fill: "none",
|
||||||
|
stroke: "currentColor",
|
||||||
|
"stroke-width": "2",
|
||||||
|
"stroke-linecap": "round",
|
||||||
|
"stroke-linejoin": "round",
|
||||||
|
"aria-hidden": "true",
|
||||||
|
},
|
||||||
|
h("path", { d: "M18 6 6 18" }),
|
||||||
|
h("path", { d: "m6 6 12 12" }),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pendingInvites.length === 0
|
||||||
|
? h(
|
||||||
|
"p",
|
||||||
|
{
|
||||||
|
className: "org-members-empty",
|
||||||
|
},
|
||||||
|
"No incoming organization invites.",
|
||||||
|
)
|
||||||
|
: h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
className:
|
||||||
|
"org-invite-menu-list",
|
||||||
|
},
|
||||||
|
...pendingInvites.map((invite) =>
|
||||||
|
h(
|
||||||
|
"article",
|
||||||
|
{
|
||||||
|
className:
|
||||||
|
"org-invite-row",
|
||||||
|
},
|
||||||
|
h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
className:
|
||||||
|
"org-name-copy",
|
||||||
|
},
|
||||||
|
h(
|
||||||
|
"strong",
|
||||||
|
null,
|
||||||
|
invite.orgName ||
|
||||||
|
"Unknown Organization",
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
"span",
|
||||||
|
{
|
||||||
|
className:
|
||||||
|
"org-name-meta",
|
||||||
|
},
|
||||||
|
"Invited by ",
|
||||||
|
invite.inviterName ||
|
||||||
|
"Unknown",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
className:
|
||||||
|
"org-invite-actions",
|
||||||
|
},
|
||||||
|
h(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
className:
|
||||||
|
"org-secondary-btn",
|
||||||
|
onClick: () =>
|
||||||
|
actions.declineInvite(
|
||||||
|
String(
|
||||||
|
invite.orgId ||
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"Decline",
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
onClick: () =>
|
||||||
|
actions.acceptInvite(
|
||||||
|
String(
|
||||||
|
invite.orgId ||
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"Accept",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
allowMemberManagement
|
|
||||||
? h(
|
|
||||||
"button",
|
|
||||||
{
|
|
||||||
type: "button",
|
|
||||||
className: "org-secondary-btn",
|
|
||||||
onClick: () => actions.openModal("invite"),
|
|
||||||
},
|
|
||||||
"Invite Player",
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
...pendingInvites.map((invite) =>
|
|
||||||
h(
|
|
||||||
"article",
|
|
||||||
{ className: "org-name-row" },
|
|
||||||
h(
|
|
||||||
"div",
|
|
||||||
{ className: "org-name-copy" },
|
|
||||||
h(
|
|
||||||
"strong",
|
|
||||||
null,
|
|
||||||
invite.orgName || "Unknown Organization",
|
|
||||||
),
|
|
||||||
h(
|
|
||||||
"span",
|
|
||||||
{ className: "org-name-meta" },
|
|
||||||
"Invited by ",
|
|
||||||
invite.inviterName || "Unknown",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
h(
|
|
||||||
"div",
|
|
||||||
{ className: "org-inline-actions" },
|
|
||||||
h(
|
|
||||||
"button",
|
|
||||||
{
|
|
||||||
type: "button",
|
|
||||||
className: "org-secondary-btn",
|
|
||||||
onClick: () =>
|
|
||||||
actions.declineInvite(
|
|
||||||
String(invite.orgId || ""),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"Decline",
|
|
||||||
),
|
|
||||||
h(
|
|
||||||
"button",
|
|
||||||
{
|
|
||||||
type: "button",
|
|
||||||
onClick: () =>
|
|
||||||
actions.acceptInvite(
|
|
||||||
String(invite.orgId || ""),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"Accept",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
h(
|
|
||||||
"div",
|
|
||||||
{ className: "org-members-section" },
|
|
||||||
h("h4", null, "Roster"),
|
|
||||||
),
|
),
|
||||||
...members.map((member) => {
|
...members.map((member) => {
|
||||||
const canRemoveMember =
|
const canRemoveMember =
|
||||||
|
|||||||
@ -85,6 +85,14 @@
|
|||||||
store.setModal(null);
|
store.setModal(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleInviteMenu() {
|
||||||
|
store.setInviteMenuOpen(!store.getInviteMenuOpen());
|
||||||
|
}
|
||||||
|
|
||||||
|
closeInviteMenu() {
|
||||||
|
store.setInviteMenuOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
removeMember(member) {
|
removeMember(member) {
|
||||||
if (!getters.canManageMembers()) {
|
if (!getters.canManageMembers()) {
|
||||||
return false;
|
return false;
|
||||||
@ -355,6 +363,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.closeInviteMenu();
|
||||||
return bridge.requestAcceptInvite({ orgId });
|
return bridge.requestAcceptInvite({ orgId });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,6 +380,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.closeInviteMenu();
|
||||||
return bridge.requestDeclineInvite({ orgId });
|
return bridge.requestDeclineInvite({ orgId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,6 +73,8 @@
|
|||||||
text: "",
|
text: "",
|
||||||
});
|
});
|
||||||
[this.getModal, this.setModal] = createSignal(null);
|
[this.getModal, this.setModal] = createSignal(null);
|
||||||
|
[this.getInviteMenuOpen, this.setInviteMenuOpen] =
|
||||||
|
createSignal(false);
|
||||||
[this.getOrgDisbanded, this.setOrgDisbanded] = createSignal(false);
|
[this.getOrgDisbanded, this.setOrgDisbanded] = createSignal(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user