@the-portland-company/shell 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/index.cjs +496 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +119 -2
- package/dist/index.d.ts +119 -2
- package/dist/index.js +493 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { extendTheme, Tooltip, ChakraProvider,
|
|
2
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { extendTheme, Tooltip, ChakraProvider, Menu, MenuButton, Box, HStack, Text, Portal, MenuList, MenuItem, Flex, MenuDivider, useDisclosure, useToast, IconButton, Modal, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, VStack, Textarea, ModalFooter, Button, useColorMode, Avatar, Heading, Spacer, Link as Link$1, Image } from '@chakra-ui/react';
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import clsx2 from 'clsx';
|
|
4
4
|
import { Link, useLocation } from 'react-router-dom';
|
|
5
|
-
import { createContext, useEffect, useState, useMemo, useContext } from 'react';
|
|
5
|
+
import { createContext, useEffect, useState, useMemo, useContext, useCallback } from 'react';
|
|
6
6
|
|
|
7
7
|
// src/theme/index.ts
|
|
8
8
|
|
|
@@ -1115,6 +1115,10 @@ function GlobalUiIdProvider() {
|
|
|
1115
1115
|
}
|
|
1116
1116
|
var ShellAuthContext = createContext(null);
|
|
1117
1117
|
var ShellMetaContext = createContext(null);
|
|
1118
|
+
var ShellOrgContext = createContext(null);
|
|
1119
|
+
var ShellLinkedAccountsContext = createContext(null);
|
|
1120
|
+
var ShellSupportProviderContext = createContext(null);
|
|
1121
|
+
var ShellChromeContext = createContext(null);
|
|
1118
1122
|
function toShellUser(session) {
|
|
1119
1123
|
if (!session?.user) return null;
|
|
1120
1124
|
const su = session.user;
|
|
@@ -1131,7 +1135,12 @@ function ShellProvider({
|
|
|
1131
1135
|
supabaseClient,
|
|
1132
1136
|
currentApp,
|
|
1133
1137
|
appRegistry,
|
|
1134
|
-
basename
|
|
1138
|
+
basename,
|
|
1139
|
+
organization,
|
|
1140
|
+
linkedAccounts,
|
|
1141
|
+
support,
|
|
1142
|
+
devNotesMenu,
|
|
1143
|
+
myProfileHref
|
|
1135
1144
|
}) {
|
|
1136
1145
|
const [status, setStatus] = useState("loading");
|
|
1137
1146
|
const [session, setSession] = useState(null);
|
|
@@ -1170,7 +1179,14 @@ function ShellProvider({
|
|
|
1170
1179
|
}),
|
|
1171
1180
|
[currentApp, appRegistry, basename]
|
|
1172
1181
|
);
|
|
1173
|
-
|
|
1182
|
+
const chrome = useMemo(
|
|
1183
|
+
() => ({
|
|
1184
|
+
devNotesMenu: devNotesMenu ?? null,
|
|
1185
|
+
myProfileHref: myProfileHref ?? "/my-profile"
|
|
1186
|
+
}),
|
|
1187
|
+
[devNotesMenu, myProfileHref]
|
|
1188
|
+
);
|
|
1189
|
+
return /* @__PURE__ */ jsx(ShellAuthContext.Provider, { value, children: /* @__PURE__ */ jsx(ShellMetaContext.Provider, { value: meta, children: /* @__PURE__ */ jsx(ShellOrgContext.Provider, { value: organization ?? null, children: /* @__PURE__ */ jsx(ShellLinkedAccountsContext.Provider, { value: linkedAccounts ?? null, children: /* @__PURE__ */ jsx(ShellSupportProviderContext.Provider, { value: support ?? null, children: /* @__PURE__ */ jsx(ShellChromeContext.Provider, { value: chrome, children: /* @__PURE__ */ jsx(ChakraProvider, { theme: politogyTheme, children }) }) }) }) }) }) });
|
|
1174
1190
|
}
|
|
1175
1191
|
function useShellAuth() {
|
|
1176
1192
|
const ctx = useContext(ShellAuthContext);
|
|
@@ -1193,8 +1209,472 @@ function useCurrentApp() {
|
|
|
1193
1209
|
}
|
|
1194
1210
|
return meta.currentApp;
|
|
1195
1211
|
}
|
|
1212
|
+
function useShellOrganization() {
|
|
1213
|
+
return useContext(ShellOrgContext);
|
|
1214
|
+
}
|
|
1215
|
+
function useShellLinkedAccounts() {
|
|
1216
|
+
return useContext(ShellLinkedAccountsContext);
|
|
1217
|
+
}
|
|
1218
|
+
function useShellSupport() {
|
|
1219
|
+
return useContext(ShellSupportProviderContext);
|
|
1220
|
+
}
|
|
1221
|
+
function useShellChrome() {
|
|
1222
|
+
const ctx = useContext(ShellChromeContext);
|
|
1223
|
+
if (!ctx) {
|
|
1224
|
+
throw new Error("useShellChrome must be used inside <ShellProvider>");
|
|
1225
|
+
}
|
|
1226
|
+
return ctx;
|
|
1227
|
+
}
|
|
1228
|
+
var HEX_COLOR_PATTERN = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
1229
|
+
function normalizeHexColor(value) {
|
|
1230
|
+
const trimmed = value?.trim();
|
|
1231
|
+
if (!trimmed || !HEX_COLOR_PATTERN.test(trimmed)) return null;
|
|
1232
|
+
if (trimmed.length === 7) return trimmed;
|
|
1233
|
+
const [r, g, b] = trimmed.slice(1).split("");
|
|
1234
|
+
return `#${r}${r}${g}${g}${b}${b}`;
|
|
1235
|
+
}
|
|
1236
|
+
function getOrganizationBadgeLetters(name) {
|
|
1237
|
+
const normalizedName = String(name || "").trim().replace(/[^a-zA-Z0-9\s]+/g, " ");
|
|
1238
|
+
const parts = normalizedName.split(/\s+/).filter(Boolean);
|
|
1239
|
+
if (parts.length >= 2) {
|
|
1240
|
+
return `${parts[0][0] || ""}${parts[1][0] || ""}`.toUpperCase();
|
|
1241
|
+
}
|
|
1242
|
+
const compact = parts[0] || normalizedName.replace(/\s+/g, "");
|
|
1243
|
+
return compact.slice(0, 2).toUpperCase() || "OR";
|
|
1244
|
+
}
|
|
1245
|
+
function OrgBadge({ name, logoUrl, brandColor, size }) {
|
|
1246
|
+
const normalizedColor = normalizeHexColor(brandColor);
|
|
1247
|
+
const badgeColor = normalizedColor || "#5a5a5a";
|
|
1248
|
+
const badgeLetters = getOrganizationBadgeLetters(name);
|
|
1249
|
+
return /* @__PURE__ */ jsx(
|
|
1250
|
+
Box,
|
|
1251
|
+
{
|
|
1252
|
+
boxSize: size,
|
|
1253
|
+
borderRadius: "full",
|
|
1254
|
+
overflow: "hidden",
|
|
1255
|
+
border: "1px solid white",
|
|
1256
|
+
flexShrink: 0,
|
|
1257
|
+
bg: logoUrl ? "whiteAlpha.300" : badgeColor,
|
|
1258
|
+
color: "white",
|
|
1259
|
+
display: "inline-flex",
|
|
1260
|
+
alignItems: "center",
|
|
1261
|
+
justifyContent: "center",
|
|
1262
|
+
fontSize: "xs",
|
|
1263
|
+
fontWeight: "bold",
|
|
1264
|
+
letterSpacing: "0.08em",
|
|
1265
|
+
textTransform: "uppercase",
|
|
1266
|
+
children: logoUrl ? /* @__PURE__ */ jsx(Image, { src: logoUrl, alt: `${name ?? "Organization"} logo`, boxSize: "full", objectFit: "cover" }) : badgeLetters
|
|
1267
|
+
}
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
function OrgSelector() {
|
|
1271
|
+
const org = useShellOrganization();
|
|
1272
|
+
if (!org) return null;
|
|
1273
|
+
const { currentOrg, organizations, switchOrganization, createOrgHref } = org;
|
|
1274
|
+
const others = organizations.filter((o) => o.id !== currentOrg?.id);
|
|
1275
|
+
return /* @__PURE__ */ jsxs(Menu, { placement: "bottom-start", children: [
|
|
1276
|
+
/* @__PURE__ */ jsx(
|
|
1277
|
+
MenuButton,
|
|
1278
|
+
{
|
|
1279
|
+
as: Box,
|
|
1280
|
+
cursor: "pointer",
|
|
1281
|
+
px: 2,
|
|
1282
|
+
py: 1,
|
|
1283
|
+
borderRadius: "md",
|
|
1284
|
+
_hover: { bg: "gray.100" },
|
|
1285
|
+
_active: { bg: "gray.200" },
|
|
1286
|
+
"aria-label": "Switch organization",
|
|
1287
|
+
children: /* @__PURE__ */ jsxs(HStack, { spacing: 2, align: "center", children: [
|
|
1288
|
+
currentOrg ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1289
|
+
/* @__PURE__ */ jsx(
|
|
1290
|
+
OrgBadge,
|
|
1291
|
+
{
|
|
1292
|
+
name: currentOrg.name,
|
|
1293
|
+
logoUrl: currentOrg.logoUrl,
|
|
1294
|
+
brandColor: currentOrg.brandColor,
|
|
1295
|
+
size: "24px"
|
|
1296
|
+
}
|
|
1297
|
+
),
|
|
1298
|
+
/* @__PURE__ */ jsx(Text, { fontSize: "sm", fontWeight: "600", color: "gray.800", noOfLines: 1, children: currentOrg.name })
|
|
1299
|
+
] }) : /* @__PURE__ */ jsx(Text, { fontSize: "sm", color: "gray.500", children: "Select organization" }),
|
|
1300
|
+
/* @__PURE__ */ jsx(Text, { as: "span", fontSize: "xs", color: "gray.500", "aria-hidden": "true", children: "\u25BE" })
|
|
1301
|
+
] })
|
|
1302
|
+
}
|
|
1303
|
+
),
|
|
1304
|
+
/* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsxs(MenuList, { zIndex: 1500, children: [
|
|
1305
|
+
others.length === 0 && /* @__PURE__ */ jsx(MenuItem, { isDisabled: true, children: /* @__PURE__ */ jsx(Text, { fontSize: "sm", color: "gray.500", children: "No other organizations" }) }),
|
|
1306
|
+
others.map((o) => /* @__PURE__ */ jsx(
|
|
1307
|
+
MenuItem,
|
|
1308
|
+
{
|
|
1309
|
+
onClick: () => {
|
|
1310
|
+
void switchOrganization(o.id);
|
|
1311
|
+
},
|
|
1312
|
+
children: /* @__PURE__ */ jsxs(HStack, { spacing: 2, align: "center", children: [
|
|
1313
|
+
/* @__PURE__ */ jsx(OrgBadge, { name: o.name, logoUrl: o.logoUrl, brandColor: o.brandColor, size: "20px" }),
|
|
1314
|
+
/* @__PURE__ */ jsx(Flex, { direction: "column", children: /* @__PURE__ */ jsx(Text, { fontSize: "sm", fontWeight: "600", children: o.name }) })
|
|
1315
|
+
] })
|
|
1316
|
+
},
|
|
1317
|
+
o.id
|
|
1318
|
+
)),
|
|
1319
|
+
createOrgHref && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1320
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
1321
|
+
/* @__PURE__ */ jsx(MenuItem, { as: "a", href: createOrgHref, children: /* @__PURE__ */ jsx(Text, { fontSize: "sm", color: "brand.500", fontWeight: "600", children: "Create organization" }) })
|
|
1322
|
+
] })
|
|
1323
|
+
] }) })
|
|
1324
|
+
] });
|
|
1325
|
+
}
|
|
1326
|
+
var SUPPORT_REQUEST_SUCCESS_MESSAGE = "Your support request was sent to Politogy leadership.";
|
|
1327
|
+
function splitName(value) {
|
|
1328
|
+
const trimmed = String(value ?? "").trim();
|
|
1329
|
+
if (!trimmed) return { firstName: "", lastName: "" };
|
|
1330
|
+
const [first, ...rest] = trimmed.split(/\s+/);
|
|
1331
|
+
return { firstName: first ?? "", lastName: rest.join(" ") };
|
|
1332
|
+
}
|
|
1333
|
+
function resolveSupportProfile(user) {
|
|
1334
|
+
if (!user) {
|
|
1335
|
+
return { firstName: "", lastName: "", email: "", phone: "", missingEmail: true, missingPhone: true };
|
|
1336
|
+
}
|
|
1337
|
+
const meta = user.raw.user_metadata ?? {};
|
|
1338
|
+
const resolvedName = String(meta.full_name ?? meta.name ?? "").trim() || String(user.email ?? "").split("@")[0] || "";
|
|
1339
|
+
const { firstName, lastName } = splitName(resolvedName);
|
|
1340
|
+
const email = String(user.email ?? "").trim();
|
|
1341
|
+
const phone = String(meta.phone ?? "").trim();
|
|
1342
|
+
return {
|
|
1343
|
+
firstName,
|
|
1344
|
+
lastName,
|
|
1345
|
+
email,
|
|
1346
|
+
phone,
|
|
1347
|
+
missingEmail: email.length === 0,
|
|
1348
|
+
missingPhone: phone.length === 0
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
function formatTimestamp(date) {
|
|
1352
|
+
return date.toLocaleString("en-US", {
|
|
1353
|
+
year: "numeric",
|
|
1354
|
+
month: "short",
|
|
1355
|
+
day: "numeric",
|
|
1356
|
+
hour: "numeric",
|
|
1357
|
+
minute: "2-digit",
|
|
1358
|
+
second: "2-digit",
|
|
1359
|
+
hour12: true
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
function buildSupportRequestMessage(input) {
|
|
1363
|
+
const submittedAt = input.submittedAt ?? /* @__PURE__ */ new Date();
|
|
1364
|
+
const iso = submittedAt.toISOString();
|
|
1365
|
+
const display = formatTimestamp(submittedAt);
|
|
1366
|
+
const trimmedSearch = String(input.search ?? "").trim();
|
|
1367
|
+
return [
|
|
1368
|
+
"A user requested support.",
|
|
1369
|
+
"",
|
|
1370
|
+
`First Name: ${input.firstName.trim() || "Unknown"}`,
|
|
1371
|
+
`Last Name: ${input.lastName.trim() || "Unknown"}`,
|
|
1372
|
+
`Organization: ${(input.organizationName ?? "").trim() || "Unknown"}`,
|
|
1373
|
+
`Email: ${input.email.trim()}`,
|
|
1374
|
+
`Phone: ${input.phone.trim()}`,
|
|
1375
|
+
`Submitted At (ISO): ${iso}`,
|
|
1376
|
+
`Submitted At (Local): ${display}`,
|
|
1377
|
+
`Page Path: ${input.pathname.trim() || "/"}`,
|
|
1378
|
+
`Page Title: ${(input.pageTitle ?? "").trim() || "Unknown"}`,
|
|
1379
|
+
`Query String: ${trimmedSearch || "None"}`
|
|
1380
|
+
].join("\n");
|
|
1381
|
+
}
|
|
1382
|
+
function SupportRequestButton() {
|
|
1383
|
+
const support = useShellSupport();
|
|
1384
|
+
const { user } = useShellAuth();
|
|
1385
|
+
const org = useShellOrganization();
|
|
1386
|
+
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
1387
|
+
const toast = useToast();
|
|
1388
|
+
const profile = useMemo(() => resolveSupportProfile(user), [user]);
|
|
1389
|
+
const [email, setEmail] = useState("");
|
|
1390
|
+
const [phone, setPhone] = useState("");
|
|
1391
|
+
const [message, setMessage] = useState("");
|
|
1392
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
1393
|
+
useEffect(() => {
|
|
1394
|
+
if (!isOpen) return;
|
|
1395
|
+
setEmail(profile.email);
|
|
1396
|
+
setPhone(profile.phone);
|
|
1397
|
+
setMessage("");
|
|
1398
|
+
setIsSubmitting(false);
|
|
1399
|
+
}, [isOpen, profile.email, profile.phone]);
|
|
1400
|
+
const handleClose = useCallback(() => {
|
|
1401
|
+
if (isSubmitting) return;
|
|
1402
|
+
onClose();
|
|
1403
|
+
}, [isSubmitting, onClose]);
|
|
1404
|
+
const handleSubmit = useCallback(async () => {
|
|
1405
|
+
if (!support) return;
|
|
1406
|
+
const resolvedEmail = (profile.missingEmail ? email : profile.email).trim();
|
|
1407
|
+
const resolvedPhone = (profile.missingPhone ? phone : profile.phone).trim();
|
|
1408
|
+
if (!resolvedEmail) {
|
|
1409
|
+
toast({ title: "Email required", status: "error", duration: 4e3, isClosable: true });
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
if (!resolvedPhone) {
|
|
1413
|
+
toast({ title: "Phone required", status: "error", duration: 4e3, isClosable: true });
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
if (!user?.id) {
|
|
1417
|
+
toast({
|
|
1418
|
+
title: "Unable to send support request",
|
|
1419
|
+
description: "You must be signed in to request support.",
|
|
1420
|
+
status: "error",
|
|
1421
|
+
duration: 4e3,
|
|
1422
|
+
isClosable: true
|
|
1423
|
+
});
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
const context = {
|
|
1427
|
+
pathname: typeof window !== "undefined" ? window.location.pathname : "/",
|
|
1428
|
+
search: typeof window !== "undefined" ? window.location.search : "",
|
|
1429
|
+
pageTitle: typeof document !== "undefined" ? document.title : void 0,
|
|
1430
|
+
organizationName: org?.currentOrg?.name ?? void 0
|
|
1431
|
+
};
|
|
1432
|
+
const formatted = buildSupportRequestMessage({
|
|
1433
|
+
firstName: profile.firstName,
|
|
1434
|
+
lastName: profile.lastName,
|
|
1435
|
+
organizationName: context.organizationName,
|
|
1436
|
+
email: resolvedEmail,
|
|
1437
|
+
phone: resolvedPhone,
|
|
1438
|
+
pathname: context.pathname,
|
|
1439
|
+
search: context.search,
|
|
1440
|
+
pageTitle: context.pageTitle
|
|
1441
|
+
});
|
|
1442
|
+
try {
|
|
1443
|
+
setIsSubmitting(true);
|
|
1444
|
+
await support.submitSupportRequest({
|
|
1445
|
+
email: resolvedEmail,
|
|
1446
|
+
phone: resolvedPhone,
|
|
1447
|
+
message: message.trim() ? `${message.trim()}
|
|
1448
|
+
|
|
1449
|
+
---
|
|
1450
|
+
|
|
1451
|
+
${formatted}` : formatted,
|
|
1452
|
+
context
|
|
1453
|
+
});
|
|
1454
|
+
toast({
|
|
1455
|
+
title: "Support request sent",
|
|
1456
|
+
description: SUPPORT_REQUEST_SUCCESS_MESSAGE,
|
|
1457
|
+
status: "success",
|
|
1458
|
+
duration: 5e3,
|
|
1459
|
+
isClosable: true
|
|
1460
|
+
});
|
|
1461
|
+
onClose();
|
|
1462
|
+
} catch (err) {
|
|
1463
|
+
const description = err instanceof Error ? err.message : "Unable to send your support request.";
|
|
1464
|
+
toast({
|
|
1465
|
+
title: "Failed to request support",
|
|
1466
|
+
description,
|
|
1467
|
+
status: "error",
|
|
1468
|
+
duration: 5e3,
|
|
1469
|
+
isClosable: true
|
|
1470
|
+
});
|
|
1471
|
+
} finally {
|
|
1472
|
+
setIsSubmitting(false);
|
|
1473
|
+
}
|
|
1474
|
+
}, [support, profile, email, phone, message, toast, user?.id, onClose, org?.currentOrg?.name]);
|
|
1475
|
+
if (!support) return null;
|
|
1476
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1477
|
+
/* @__PURE__ */ jsx(
|
|
1478
|
+
IconButton,
|
|
1479
|
+
{
|
|
1480
|
+
"aria-label": "Request support",
|
|
1481
|
+
icon: /* @__PURE__ */ jsx(LifebuoyIcon, {}),
|
|
1482
|
+
variant: "ghost",
|
|
1483
|
+
size: "sm",
|
|
1484
|
+
onClick: onOpen
|
|
1485
|
+
}
|
|
1486
|
+
),
|
|
1487
|
+
/* @__PURE__ */ jsxs(Modal, { isOpen, onClose: handleClose, isCentered: true, children: [
|
|
1488
|
+
/* @__PURE__ */ jsx(ModalOverlay, {}),
|
|
1489
|
+
/* @__PURE__ */ jsxs(ModalContent, { children: [
|
|
1490
|
+
/* @__PURE__ */ jsx(ModalHeader, { children: "Support" }),
|
|
1491
|
+
/* @__PURE__ */ jsx(ModalCloseButton, { isDisabled: isSubmitting }),
|
|
1492
|
+
/* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(VStack, { align: "stretch", spacing: 4, children: [
|
|
1493
|
+
/* @__PURE__ */ jsx(Text, { fontSize: "sm", color: "gray.600", children: "A message will be texted and emailed with your contact information and support will reply as soon as possible. If you are a beta customer that is typically within minutes." }),
|
|
1494
|
+
/* @__PURE__ */ jsx(Box, { rounded: "md", borderWidth: "1px", borderColor: "gray.200", bg: "gray.50", p: 3, children: /* @__PURE__ */ jsxs(VStack, { align: "stretch", spacing: 1, children: [
|
|
1495
|
+
/* @__PURE__ */ jsxs(Text, { fontSize: "sm", children: [
|
|
1496
|
+
/* @__PURE__ */ jsx("strong", { children: "Name:" }),
|
|
1497
|
+
" ",
|
|
1498
|
+
[profile.firstName, profile.lastName].filter(Boolean).join(" ") || "Unknown"
|
|
1499
|
+
] }),
|
|
1500
|
+
/* @__PURE__ */ jsxs(Text, { fontSize: "sm", children: [
|
|
1501
|
+
/* @__PURE__ */ jsx("strong", { children: "Organization:" }),
|
|
1502
|
+
" ",
|
|
1503
|
+
org?.currentOrg?.name ?? "Unknown"
|
|
1504
|
+
] }),
|
|
1505
|
+
/* @__PURE__ */ jsxs(Text, { fontSize: "sm", children: [
|
|
1506
|
+
/* @__PURE__ */ jsx("strong", { children: "Email:" }),
|
|
1507
|
+
" ",
|
|
1508
|
+
(profile.missingEmail ? email : profile.email) || "Missing"
|
|
1509
|
+
] }),
|
|
1510
|
+
/* @__PURE__ */ jsxs(Text, { fontSize: "sm", children: [
|
|
1511
|
+
/* @__PURE__ */ jsx("strong", { children: "Phone:" }),
|
|
1512
|
+
" ",
|
|
1513
|
+
(profile.missingPhone ? phone : profile.phone) || "Missing"
|
|
1514
|
+
] })
|
|
1515
|
+
] }) }),
|
|
1516
|
+
profile.missingEmail && /* @__PURE__ */ jsxs(Box, { children: [
|
|
1517
|
+
/* @__PURE__ */ jsx(Text, { fontSize: "xs", fontWeight: "600", color: "gray.700", mb: 1, children: "Email" }),
|
|
1518
|
+
/* @__PURE__ */ jsx(
|
|
1519
|
+
"input",
|
|
1520
|
+
{
|
|
1521
|
+
type: "email",
|
|
1522
|
+
"aria-label": "Email",
|
|
1523
|
+
value: email,
|
|
1524
|
+
onChange: (e) => setEmail(e.target.value),
|
|
1525
|
+
placeholder: "name@example.com",
|
|
1526
|
+
style: {
|
|
1527
|
+
width: "100%",
|
|
1528
|
+
padding: "8px 12px",
|
|
1529
|
+
border: "1px solid #e2e8f0",
|
|
1530
|
+
borderRadius: "6px",
|
|
1531
|
+
fontSize: "14px"
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
)
|
|
1535
|
+
] }),
|
|
1536
|
+
profile.missingPhone && /* @__PURE__ */ jsxs(Box, { children: [
|
|
1537
|
+
/* @__PURE__ */ jsx(Text, { fontSize: "xs", fontWeight: "600", color: "gray.700", mb: 1, children: "Phone" }),
|
|
1538
|
+
/* @__PURE__ */ jsx(
|
|
1539
|
+
"input",
|
|
1540
|
+
{
|
|
1541
|
+
"aria-label": "Phone",
|
|
1542
|
+
value: phone,
|
|
1543
|
+
onChange: (e) => setPhone(e.target.value),
|
|
1544
|
+
placeholder: "(503) 555-1212",
|
|
1545
|
+
style: {
|
|
1546
|
+
width: "100%",
|
|
1547
|
+
padding: "8px 12px",
|
|
1548
|
+
border: "1px solid #e2e8f0",
|
|
1549
|
+
borderRadius: "6px",
|
|
1550
|
+
fontSize: "14px"
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
)
|
|
1554
|
+
] }),
|
|
1555
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1556
|
+
/* @__PURE__ */ jsx(Text, { fontSize: "xs", fontWeight: "600", color: "gray.700", mb: 1, children: "Optional message" }),
|
|
1557
|
+
/* @__PURE__ */ jsx(
|
|
1558
|
+
Textarea,
|
|
1559
|
+
{
|
|
1560
|
+
value: message,
|
|
1561
|
+
onChange: (e) => setMessage(e.target.value),
|
|
1562
|
+
placeholder: "What can we help you with?",
|
|
1563
|
+
rows: 3
|
|
1564
|
+
}
|
|
1565
|
+
)
|
|
1566
|
+
] })
|
|
1567
|
+
] }) }),
|
|
1568
|
+
/* @__PURE__ */ jsxs(ModalFooter, { children: [
|
|
1569
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", mr: 3, onClick: handleClose, isDisabled: isSubmitting, children: "Cancel" }),
|
|
1570
|
+
/* @__PURE__ */ jsx(
|
|
1571
|
+
Button,
|
|
1572
|
+
{
|
|
1573
|
+
colorScheme: "orange",
|
|
1574
|
+
onClick: () => void handleSubmit(),
|
|
1575
|
+
isLoading: isSubmitting,
|
|
1576
|
+
loadingText: "Sending",
|
|
1577
|
+
children: "Request Support"
|
|
1578
|
+
}
|
|
1579
|
+
)
|
|
1580
|
+
] })
|
|
1581
|
+
] })
|
|
1582
|
+
] })
|
|
1583
|
+
] });
|
|
1584
|
+
}
|
|
1585
|
+
function LifebuoyIcon() {
|
|
1586
|
+
return /* @__PURE__ */ jsxs(
|
|
1587
|
+
"svg",
|
|
1588
|
+
{
|
|
1589
|
+
width: "18",
|
|
1590
|
+
height: "18",
|
|
1591
|
+
viewBox: "0 0 24 24",
|
|
1592
|
+
fill: "none",
|
|
1593
|
+
stroke: "currentColor",
|
|
1594
|
+
strokeWidth: "2",
|
|
1595
|
+
strokeLinecap: "round",
|
|
1596
|
+
strokeLinejoin: "round",
|
|
1597
|
+
"aria-hidden": "true",
|
|
1598
|
+
children: [
|
|
1599
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1600
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4" }),
|
|
1601
|
+
/* @__PURE__ */ jsx("line", { x1: "4.93", y1: "4.93", x2: "9.17", y2: "9.17" }),
|
|
1602
|
+
/* @__PURE__ */ jsx("line", { x1: "14.83", y1: "14.83", x2: "19.07", y2: "19.07" }),
|
|
1603
|
+
/* @__PURE__ */ jsx("line", { x1: "14.83", y1: "9.17", x2: "19.07", y2: "4.93" }),
|
|
1604
|
+
/* @__PURE__ */ jsx("line", { x1: "14.83", y1: "9.17", x2: "18.36", y2: "5.64" }),
|
|
1605
|
+
/* @__PURE__ */ jsx("line", { x1: "4.93", y1: "19.07", x2: "9.17", y2: "14.83" })
|
|
1606
|
+
]
|
|
1607
|
+
}
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
function avatarUrlFromUser(user) {
|
|
1611
|
+
if (!user) return void 0;
|
|
1612
|
+
const meta = user.raw.user_metadata;
|
|
1613
|
+
return meta?.avatar_url ?? void 0;
|
|
1614
|
+
}
|
|
1615
|
+
function UserMenu() {
|
|
1616
|
+
const { user, status, signOut } = useShellAuth();
|
|
1617
|
+
const { myProfileHref } = useShellChrome();
|
|
1618
|
+
const linked = useShellLinkedAccounts();
|
|
1619
|
+
const { colorMode, toggleColorMode } = useColorMode();
|
|
1620
|
+
if (status !== "authenticated" || !user) return null;
|
|
1621
|
+
const displayName = user.displayName ?? user.email ?? "User";
|
|
1622
|
+
const avatarUrl = avatarUrlFromUser(user);
|
|
1623
|
+
return /* @__PURE__ */ jsxs(Menu, { placement: "bottom-end", children: [
|
|
1624
|
+
/* @__PURE__ */ jsx(
|
|
1625
|
+
MenuButton,
|
|
1626
|
+
{
|
|
1627
|
+
"aria-label": "Open account menu",
|
|
1628
|
+
as: Box,
|
|
1629
|
+
cursor: "pointer",
|
|
1630
|
+
borderRadius: "full",
|
|
1631
|
+
_hover: { opacity: 0.85 },
|
|
1632
|
+
children: /* @__PURE__ */ jsx(Avatar, { size: "sm", name: displayName, src: avatarUrl })
|
|
1633
|
+
}
|
|
1634
|
+
),
|
|
1635
|
+
/* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsxs(MenuList, { zIndex: 1500, children: [
|
|
1636
|
+
/* @__PURE__ */ jsxs(Box, { px: 3, py: 2, children: [
|
|
1637
|
+
/* @__PURE__ */ jsx(Text, { fontSize: "sm", fontWeight: "600", noOfLines: 1, children: displayName }),
|
|
1638
|
+
user.email && /* @__PURE__ */ jsx(Text, { fontSize: "xs", color: "gray.500", noOfLines: 1, children: user.email })
|
|
1639
|
+
] }),
|
|
1640
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
1641
|
+
/* @__PURE__ */ jsx(MenuItem, { as: "a", href: myProfileHref, children: "My Profile" }),
|
|
1642
|
+
/* @__PURE__ */ jsx(MenuItem, { onClick: toggleColorMode, children: colorMode === "light" ? "Switch to dark mode" : "Switch to light mode" }),
|
|
1643
|
+
/* @__PURE__ */ jsx(MenuItem, { onClick: () => void signOut(), children: "Sign out" }),
|
|
1644
|
+
linked && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1645
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
1646
|
+
/* @__PURE__ */ jsx(Box, { px: 3, pt: 1, pb: 1, children: /* @__PURE__ */ jsx(Text, { fontSize: "xs", textTransform: "uppercase", letterSpacing: "0.08em", color: "gray.500", children: "Switch account" }) }),
|
|
1647
|
+
linked.linkedAccounts.length === 0 && /* @__PURE__ */ jsx(MenuItem, { isDisabled: true, children: /* @__PURE__ */ jsx(Text, { fontSize: "sm", color: "gray.500", children: "No linked accounts" }) }),
|
|
1648
|
+
linked.linkedAccounts.map((acct) => /* @__PURE__ */ jsx(
|
|
1649
|
+
MenuItem,
|
|
1650
|
+
{
|
|
1651
|
+
onClick: () => {
|
|
1652
|
+
void linked.switchToAccount(acct.id);
|
|
1653
|
+
},
|
|
1654
|
+
children: /* @__PURE__ */ jsxs(HStack, { spacing: 2, align: "center", children: [
|
|
1655
|
+
/* @__PURE__ */ jsx(
|
|
1656
|
+
Avatar,
|
|
1657
|
+
{
|
|
1658
|
+
size: "xs",
|
|
1659
|
+
name: acct.displayName ?? acct.email,
|
|
1660
|
+
src: acct.avatarUrl ?? void 0
|
|
1661
|
+
}
|
|
1662
|
+
),
|
|
1663
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", minW: 0, children: [
|
|
1664
|
+
/* @__PURE__ */ jsx(Text, { fontSize: "sm", fontWeight: "600", noOfLines: 1, children: acct.displayName ?? acct.email }),
|
|
1665
|
+
acct.displayName && /* @__PURE__ */ jsx(Text, { fontSize: "xs", color: "gray.500", noOfLines: 1, children: acct.email })
|
|
1666
|
+
] })
|
|
1667
|
+
] })
|
|
1668
|
+
},
|
|
1669
|
+
acct.id
|
|
1670
|
+
)),
|
|
1671
|
+
/* @__PURE__ */ jsx(MenuItem, { onClick: linked.onAddAccount, children: "Add account" })
|
|
1672
|
+
] })
|
|
1673
|
+
] }) })
|
|
1674
|
+
] });
|
|
1675
|
+
}
|
|
1196
1676
|
function Header({ extrasSlot }) {
|
|
1197
|
-
const {
|
|
1677
|
+
const { devNotesMenu } = useShellChrome();
|
|
1198
1678
|
return /* @__PURE__ */ jsxs(
|
|
1199
1679
|
Flex,
|
|
1200
1680
|
{
|
|
@@ -1205,14 +1685,15 @@ function Header({ extrasSlot }) {
|
|
|
1205
1685
|
bg: "white",
|
|
1206
1686
|
borderBottom: "1px solid",
|
|
1207
1687
|
borderColor: "gray.200",
|
|
1688
|
+
gap: 3,
|
|
1208
1689
|
children: [
|
|
1209
1690
|
/* @__PURE__ */ jsx(Heading, { size: "md", color: "brand.500", children: "politogy" }),
|
|
1691
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(OrgSelector, {}) }),
|
|
1210
1692
|
/* @__PURE__ */ jsx(Spacer, {}),
|
|
1211
|
-
extrasSlot && /* @__PURE__ */ jsx(Box, {
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
] })
|
|
1693
|
+
extrasSlot && /* @__PURE__ */ jsx(Box, { children: extrasSlot }),
|
|
1694
|
+
/* @__PURE__ */ jsx(SupportRequestButton, {}),
|
|
1695
|
+
devNotesMenu,
|
|
1696
|
+
/* @__PURE__ */ jsx(UserMenu, {})
|
|
1216
1697
|
]
|
|
1217
1698
|
}
|
|
1218
1699
|
);
|
|
@@ -1326,6 +1807,6 @@ function buildSpeculationRules(currentApp, registry) {
|
|
|
1326
1807
|
return JSON.stringify(payload);
|
|
1327
1808
|
}
|
|
1328
1809
|
|
|
1329
|
-
export { AppLayout, BreadcrumbBar, Card, Footer, GlobalUiIdProvider, Header, HeaderTabBar, PageContainer, PageHeader, ShellProvider, Sidebar, buildSpeculationRules, politogyTheme, registerShellPrecache, useAppRegistry, useCurrentApp, useShellAuth };
|
|
1810
|
+
export { AppLayout, BreadcrumbBar, Card, Footer, GlobalUiIdProvider, Header, HeaderTabBar, OrgSelector, PageContainer, PageHeader, ShellProvider, Sidebar, SupportRequestButton, UserMenu, buildSpeculationRules, politogyTheme, registerShellPrecache, useAppRegistry, useCurrentApp, useShellAuth, useShellChrome, useShellLinkedAccounts, useShellOrganization, useShellSupport };
|
|
1330
1811
|
//# sourceMappingURL=index.js.map
|
|
1331
1812
|
//# sourceMappingURL=index.js.map
|