@axcode/axcloud-sdk 0.1.6 → 0.1.7-dev.580a922

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/dist/index.js CHANGED
@@ -124,7 +124,7 @@ var AxCloudClient = class {
124
124
  */
125
125
  shouldAttachApiKey(path) {
126
126
  const normalized = path.startsWith("/") ? path : `/${path}`;
127
- return normalized.startsWith("/public/") || normalized.startsWith("/api/public/") || normalized.startsWith("/content/public/");
127
+ return normalized.startsWith("/public/") || normalized.startsWith("/api/public/") || normalized.startsWith("/content/public/") || normalized.startsWith("/media/public/") || normalized.startsWith("/documents/public/") || normalized.startsWith("/barnsport/public/") || normalized.startsWith("/api/barnsport/public/");
128
128
  }
129
129
  /**
130
130
  * Make an authenticated request
@@ -433,6 +433,98 @@ function createFormHelper(config) {
433
433
  })
434
434
  };
435
435
  }
436
+
437
+ // src/core/voting.ts
438
+ function baseOf(votingApiUrl) {
439
+ return votingApiUrl.replace(/\/$/, "");
440
+ }
441
+ async function readJson(response) {
442
+ const json = await response.json().catch(() => ({}));
443
+ if (json && typeof json === "object" && "success" in json && "data" in json) {
444
+ return json.data;
445
+ }
446
+ return json;
447
+ }
448
+ async function ensureOk(response) {
449
+ if (!response.ok) {
450
+ const body = await response.json().catch(() => ({}));
451
+ const message = body && (body.error || body.message) || `Request failed with status ${response.status}`;
452
+ throw new Error(message);
453
+ }
454
+ }
455
+ async function checkVotingCode(votingApiUrl, params) {
456
+ const response = await fetch(
457
+ `${baseOf(votingApiUrl)}/public/organizations/${params.orgId}/polls/${params.pollId}/eligibility`,
458
+ {
459
+ method: "POST",
460
+ headers: { "Content-Type": "application/json" },
461
+ body: JSON.stringify({ code: params.code })
462
+ }
463
+ );
464
+ await ensureOk(response);
465
+ return readJson(response);
466
+ }
467
+ async function castVoteWithCode(votingApiUrl, params) {
468
+ const response = await fetch(
469
+ `${baseOf(votingApiUrl)}/public/organizations/${params.orgId}/polls/${params.pollId}/vote`,
470
+ {
471
+ method: "POST",
472
+ headers: { "Content-Type": "application/json" },
473
+ body: JSON.stringify({ code: params.code, selected_options: params.selectedOptions, rankings: params.rankings })
474
+ }
475
+ );
476
+ await ensureOk(response);
477
+ return readJson(response);
478
+ }
479
+ async function getVotingReceipt(votingApiUrl, params) {
480
+ const response = await fetch(
481
+ `${baseOf(votingApiUrl)}/public/organizations/${params.orgId}/polls/${params.pollId}/receipt`,
482
+ {
483
+ method: "POST",
484
+ headers: { "Content-Type": "application/json" },
485
+ body: JSON.stringify({ code: params.code })
486
+ }
487
+ );
488
+ await ensureOk(response);
489
+ return readJson(response);
490
+ }
491
+ function authHeaders(accessToken) {
492
+ return { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}` };
493
+ }
494
+ async function getBallot(votingApiUrl, params) {
495
+ const base = `${baseOf(votingApiUrl)}/organizations/${params.orgId}/polls/${params.pollId}`;
496
+ const pollResp = await fetch(base, { headers: authHeaders(params.accessToken) });
497
+ await ensureOk(pollResp);
498
+ const poll = await readJson(pollResp);
499
+ let candidates = [];
500
+ if (poll.poll_type === "election") {
501
+ const candResp = await fetch(`${base}/candidates`, { headers: authHeaders(params.accessToken) });
502
+ await ensureOk(candResp);
503
+ const data = await readJson(candResp);
504
+ candidates = data.candidates || [];
505
+ }
506
+ return { ...poll, candidates };
507
+ }
508
+ async function checkEligibility(votingApiUrl, params) {
509
+ const response = await fetch(
510
+ `${baseOf(votingApiUrl)}/organizations/${params.orgId}/polls/${params.pollId}/eligibility`,
511
+ { headers: authHeaders(params.accessToken) }
512
+ );
513
+ await ensureOk(response);
514
+ return readJson(response);
515
+ }
516
+ async function castVote(votingApiUrl, params) {
517
+ const response = await fetch(
518
+ `${baseOf(votingApiUrl)}/organizations/${params.orgId}/polls/${params.pollId}/vote`,
519
+ {
520
+ method: "POST",
521
+ headers: authHeaders(params.accessToken),
522
+ body: JSON.stringify({ selected_options: params.selectedOptions, rankings: params.rankings })
523
+ }
524
+ );
525
+ await ensureOk(response);
526
+ return readJson(response);
527
+ }
436
528
  var AxCloudContext = react.createContext(null);
437
529
  function useAxCloudContext() {
438
530
  const context = react.useContext(AxCloudContext);
@@ -743,6 +835,7 @@ function useNews(options = {}) {
743
835
  search,
744
836
  sortBy = "publishedAt",
745
837
  sortOrder = "desc",
838
+ lang,
746
839
  publicOnly = false
747
840
  } = options;
748
841
  const usePublicEndpoint = isPublicMode || publicOnly;
@@ -759,7 +852,8 @@ function useNews(options = {}) {
759
852
  sectionId,
760
853
  search,
761
854
  sortBy,
762
- sortOrder
855
+ sortOrder,
856
+ lang
763
857
  ],
764
858
  queryFn: async () => {
765
859
  const endpoint = usePublicEndpoint ? `/content/public/${orgId}/news` : `/content/members/${orgId}/news`;
@@ -771,7 +865,8 @@ function useNews(options = {}) {
771
865
  sectionId,
772
866
  search,
773
867
  sortBy,
774
- sortOrder
868
+ sortOrder,
869
+ lang
775
870
  });
776
871
  },
777
872
  staleTime: 1e3 * 60 * 5
@@ -1000,6 +1095,76 @@ function useUpdateFormSubmission() {
1000
1095
  }
1001
1096
  });
1002
1097
  }
1098
+ function useCodeBallot({ pollId, votingApiUrl }) {
1099
+ const { orgId, config } = useAxCloudContext();
1100
+ const baseUrl = votingApiUrl || `${config.apiUrl.replace(/\/$/, "")}/voting`;
1101
+ const [stage, setStage] = react.useState("enter_code");
1102
+ const [code, setCode] = react.useState("");
1103
+ const [ballot, setBallot] = react.useState(null);
1104
+ const [receipt, setReceipt] = react.useState(null);
1105
+ const [reason, setReason] = react.useState(void 0);
1106
+ const [loading, setLoading] = react.useState(false);
1107
+ const [error, setError] = react.useState(null);
1108
+ const validateCode = react.useCallback(
1109
+ async (inputCode) => {
1110
+ setLoading(true);
1111
+ setError(null);
1112
+ try {
1113
+ const result = await checkVotingCode(baseUrl, { orgId, pollId, code: inputCode });
1114
+ setCode(inputCode);
1115
+ setReason(result.reason);
1116
+ if (result.has_voted) {
1117
+ const r = await getVotingReceipt(baseUrl, { orgId, pollId, code: inputCode }).catch(() => null);
1118
+ setReceipt(r);
1119
+ setStage("already_voted");
1120
+ } else if (result.eligible && result.ballot) {
1121
+ setBallot(result.ballot);
1122
+ setStage("ballot");
1123
+ } else {
1124
+ setError(result.reason || "This code cannot be used to vote right now.");
1125
+ }
1126
+ return result;
1127
+ } catch (e) {
1128
+ setError(e instanceof Error ? e.message : "Failed to validate code");
1129
+ return null;
1130
+ } finally {
1131
+ setLoading(false);
1132
+ }
1133
+ },
1134
+ [baseUrl, orgId, pollId]
1135
+ );
1136
+ const submitVote = react.useCallback(
1137
+ async (selectedOptions, rankings) => {
1138
+ setLoading(true);
1139
+ setError(null);
1140
+ try {
1141
+ await castVoteWithCode(baseUrl, { orgId, pollId, code, selectedOptions, rankings });
1142
+ const r = await getVotingReceipt(baseUrl, { orgId, pollId, code }).catch(() => null);
1143
+ setReceipt(r);
1144
+ setStage("submitted");
1145
+ return true;
1146
+ } catch (e) {
1147
+ setError(e instanceof Error ? e.message : "Failed to submit vote");
1148
+ return false;
1149
+ } finally {
1150
+ setLoading(false);
1151
+ }
1152
+ },
1153
+ [baseUrl, orgId, pollId, code]
1154
+ );
1155
+ const reset = react.useCallback(() => {
1156
+ setStage("enter_code");
1157
+ setCode("");
1158
+ setBallot(null);
1159
+ setReceipt(null);
1160
+ setReason(void 0);
1161
+ setError(null);
1162
+ }, []);
1163
+ return react.useMemo(
1164
+ () => ({ stage, code, ballot, receipt, reason, loading, error, validateCode, submitVote, reset }),
1165
+ [stage, code, ballot, receipt, reason, loading, error, validateCode, submitVote, reset]
1166
+ );
1167
+ }
1003
1168
  var LINKED_ACCOUNTS_QUERY_KEY = ["axcloud", "linked-accounts"];
1004
1169
  function useLinkedAccounts() {
1005
1170
  const { client, stage } = useAxCloudContext();
@@ -1158,6 +1323,245 @@ function useMedia(mediaId) {
1158
1323
  refetch: query.refetch
1159
1324
  };
1160
1325
  }
1326
+ function buildDocumentParams(options) {
1327
+ return {
1328
+ search: options?.search,
1329
+ tags: options?.tags?.join(","),
1330
+ limit: options?.limit
1331
+ };
1332
+ }
1333
+ function useDocuments(options) {
1334
+ const { client, orgId } = useAxCloudContext();
1335
+ const params = buildDocumentParams(options);
1336
+ const query = reactQuery.useQuery({
1337
+ queryKey: ["axcloud", "documents", "list", orgId, options],
1338
+ queryFn: async () => {
1339
+ return client.get(`/documents/public/${orgId}/documents`, params);
1340
+ },
1341
+ staleTime: 1e3 * 60 * 5
1342
+ });
1343
+ return {
1344
+ documents: query.data?.items ?? [],
1345
+ items: query.data?.items ?? [],
1346
+ count: query.data?.count ?? 0,
1347
+ isLoading: query.isLoading,
1348
+ isError: query.isError,
1349
+ error: query.error,
1350
+ refetch: query.refetch
1351
+ };
1352
+ }
1353
+ function useDocumentDownload(documentId) {
1354
+ const { client, orgId } = useAxCloudContext();
1355
+ const query = reactQuery.useQuery({
1356
+ queryKey: ["axcloud", "documents", "download", orgId, documentId],
1357
+ queryFn: async () => {
1358
+ return client.get(
1359
+ `/documents/public/${orgId}/documents/${encodeURIComponent(documentId || "")}/download`
1360
+ );
1361
+ },
1362
+ enabled: !!documentId,
1363
+ staleTime: 1e3 * 60 * 10,
1364
+ gcTime: 1e3 * 60 * 14
1365
+ });
1366
+ return {
1367
+ url: query.data?.url ?? null,
1368
+ documentUrl: query.data?.url ?? null,
1369
+ filename: query.data?.filename ?? null,
1370
+ mimeType: query.data?.mimeType ?? null,
1371
+ expiresIn: query.data?.expiresIn ?? null,
1372
+ isLoading: query.isLoading,
1373
+ isError: query.isError,
1374
+ error: query.error,
1375
+ refetch: query.refetch
1376
+ };
1377
+ }
1378
+ function useMemberDocuments(options) {
1379
+ const { client, orgId } = useAxCloudContext();
1380
+ const params = buildDocumentParams(options);
1381
+ const folderId = options?.folderId;
1382
+ const query = reactQuery.useQuery({
1383
+ queryKey: ["axcloud", "documents", "member", "list", orgId, options],
1384
+ queryFn: async () => {
1385
+ return client.get(`/documents/members/${orgId}/documents`, params);
1386
+ },
1387
+ staleTime: 1e3 * 60 * 5
1388
+ });
1389
+ const allItems = query.data?.items ?? [];
1390
+ const items = folderId ? allItems.filter((doc) => doc.folder_ids?.includes(folderId)) : allItems;
1391
+ return {
1392
+ documents: items,
1393
+ items,
1394
+ count: folderId ? items.length : query.data?.count ?? 0,
1395
+ isLoading: query.isLoading,
1396
+ isError: query.isError,
1397
+ error: query.error,
1398
+ refetch: query.refetch
1399
+ };
1400
+ }
1401
+ function useMemberDocumentFolders() {
1402
+ const { client, orgId } = useAxCloudContext();
1403
+ const query = reactQuery.useQuery({
1404
+ queryKey: ["axcloud", "documents", "member", "folders", orgId],
1405
+ queryFn: async () => {
1406
+ return client.get(
1407
+ `/documents/members/${orgId}/document-folders`
1408
+ );
1409
+ },
1410
+ staleTime: 1e3 * 60 * 5
1411
+ });
1412
+ return {
1413
+ folders: query.data?.folders ?? [],
1414
+ isLoading: query.isLoading,
1415
+ isError: query.isError,
1416
+ error: query.error,
1417
+ refetch: query.refetch
1418
+ };
1419
+ }
1420
+ function useMemberDocumentDownload(documentId) {
1421
+ const { client, orgId } = useAxCloudContext();
1422
+ const query = reactQuery.useQuery({
1423
+ queryKey: ["axcloud", "documents", "member", "download", orgId, documentId],
1424
+ queryFn: async () => {
1425
+ return client.get(
1426
+ `/documents/members/${orgId}/documents/${encodeURIComponent(documentId || "")}/download`
1427
+ );
1428
+ },
1429
+ enabled: !!documentId,
1430
+ staleTime: 1e3 * 60 * 10,
1431
+ gcTime: 1e3 * 60 * 14
1432
+ });
1433
+ return {
1434
+ url: query.data?.url ?? null,
1435
+ documentUrl: query.data?.url ?? null,
1436
+ filename: query.data?.filename ?? null,
1437
+ mimeType: query.data?.mimeType ?? null,
1438
+ expiresIn: query.data?.expiresIn ?? null,
1439
+ isLoading: query.isLoading,
1440
+ isError: query.isError,
1441
+ error: query.error,
1442
+ refetch: query.refetch
1443
+ };
1444
+ }
1445
+ function useBarnsportMunicipalities() {
1446
+ const { client, orgId } = useAxCloudContext();
1447
+ const query = reactQuery.useQuery({
1448
+ queryKey: ["axcloud", "barnsport", "municipalities", orgId],
1449
+ queryFn: () => client.get(
1450
+ `/barnsport/public/${orgId}/municipalities`
1451
+ ),
1452
+ staleTime: 1e3 * 60 * 30
1453
+ });
1454
+ return {
1455
+ municipalities: query.data?.items ?? [],
1456
+ count: query.data?.count ?? 0,
1457
+ isLoading: query.isLoading,
1458
+ isError: query.isError,
1459
+ error: query.error,
1460
+ refetch: query.refetch
1461
+ };
1462
+ }
1463
+ function useBarnsportSports() {
1464
+ const { client, orgId } = useAxCloudContext();
1465
+ const query = reactQuery.useQuery({
1466
+ queryKey: ["axcloud", "barnsport", "sports", orgId],
1467
+ queryFn: () => client.get(
1468
+ `/barnsport/public/${orgId}/sports`
1469
+ ),
1470
+ staleTime: 1e3 * 60 * 30
1471
+ });
1472
+ return {
1473
+ sports: query.data?.items ?? [],
1474
+ count: query.data?.count ?? 0,
1475
+ isLoading: query.isLoading,
1476
+ isError: query.isError,
1477
+ error: query.error,
1478
+ refetch: query.refetch
1479
+ };
1480
+ }
1481
+ function useBarnsportSport(slug) {
1482
+ const { client, orgId } = useAxCloudContext();
1483
+ const query = reactQuery.useQuery({
1484
+ queryKey: ["axcloud", "barnsport", "sport", orgId, slug],
1485
+ queryFn: () => client.get(
1486
+ `/barnsport/public/${orgId}/sports/${slug || ""}`
1487
+ ),
1488
+ enabled: Boolean(slug),
1489
+ staleTime: 1e3 * 60 * 15
1490
+ });
1491
+ return {
1492
+ sport: query.data?.sport ?? null,
1493
+ isLoading: query.isLoading,
1494
+ isError: query.isError,
1495
+ error: query.error,
1496
+ refetch: query.refetch
1497
+ };
1498
+ }
1499
+ function useBarnsportActivities(filters = {}) {
1500
+ const { client, orgId } = useAxCloudContext();
1501
+ const params = { ...filters };
1502
+ const query = reactQuery.useQuery({
1503
+ queryKey: ["axcloud", "barnsport", "activities", orgId, filters],
1504
+ queryFn: () => client.get(
1505
+ `/barnsport/public/${orgId}/activities`,
1506
+ params
1507
+ ),
1508
+ staleTime: 1e3 * 60 * 5
1509
+ });
1510
+ return {
1511
+ activities: query.data?.items ?? [],
1512
+ count: query.data?.count ?? 0,
1513
+ nextCursor: query.data?.nextCursor ?? null,
1514
+ isLoading: query.isLoading,
1515
+ isError: query.isError,
1516
+ error: query.error,
1517
+ refetch: query.refetch
1518
+ };
1519
+ }
1520
+ function useBarnsportActivity(slug) {
1521
+ const { client, orgId } = useAxCloudContext();
1522
+ const query = reactQuery.useQuery({
1523
+ queryKey: ["axcloud", "barnsport", "activity", orgId, slug],
1524
+ queryFn: () => client.get(
1525
+ `/barnsport/public/${orgId}/activities/${slug || ""}`
1526
+ ),
1527
+ enabled: Boolean(slug),
1528
+ staleTime: 1e3 * 60 * 5
1529
+ });
1530
+ return {
1531
+ activity: query.data?.activity ?? null,
1532
+ isLoading: query.isLoading,
1533
+ isError: query.isError,
1534
+ error: query.error,
1535
+ refetch: query.refetch
1536
+ };
1537
+ }
1538
+ function useBarnsportSitemap(baseUrl) {
1539
+ const { client, orgId } = useAxCloudContext();
1540
+ const query = reactQuery.useQuery({
1541
+ queryKey: ["axcloud", "barnsport", "sitemap", orgId, baseUrl],
1542
+ queryFn: () => client.get(`/barnsport/public/${orgId}/sitemap`, {
1543
+ baseUrl
1544
+ }),
1545
+ staleTime: 1e3 * 60 * 15
1546
+ });
1547
+ return {
1548
+ sitemap: query.data ?? null,
1549
+ urls: query.data?.urls ?? [],
1550
+ isLoading: query.isLoading,
1551
+ isError: query.isError,
1552
+ error: query.error,
1553
+ refetch: query.refetch
1554
+ };
1555
+ }
1556
+ function useSubmitBarnsportInterest() {
1557
+ const { client, orgId } = useAxCloudContext();
1558
+ return reactQuery.useMutation({
1559
+ mutationFn: (submission) => client.post(
1560
+ `/barnsport/public/${orgId}/interest`,
1561
+ submission
1562
+ )
1563
+ });
1564
+ }
1161
1565
  function LoginButton({
1162
1566
  children = "Log in",
1163
1567
  returnTo,
@@ -1409,31 +1813,50 @@ exports.LoginButton = LoginButton;
1409
1813
  exports.LogoutButton = LogoutButton;
1410
1814
  exports.ModuleGate = ModuleGate;
1411
1815
  exports.ProtectedRoute = ProtectedRoute;
1816
+ exports.castVote = castVote;
1817
+ exports.castVoteWithCode = castVoteWithCode;
1818
+ exports.checkEligibility = checkEligibility;
1819
+ exports.checkVotingCode = checkVotingCode;
1412
1820
  exports.createClient = createClient;
1413
1821
  exports.createContentSlotReader = createContentSlotReader;
1414
1822
  exports.createFormHelper = createFormHelper;
1823
+ exports.getBallot = getBallot;
1415
1824
  exports.getClient = getClient;
1416
1825
  exports.getContentSlotMap = getContentSlotMap;
1826
+ exports.getVotingReceipt = getVotingReceipt;
1417
1827
  exports.isAxCloudError = isAxCloudError;
1418
1828
  exports.submitForm = submitForm;
1419
1829
  exports.useAuth = useAuth;
1420
1830
  exports.useAvatar = useAvatar;
1421
1831
  exports.useAxCloudContext = useAxCloudContext;
1832
+ exports.useBarnsportActivities = useBarnsportActivities;
1833
+ exports.useBarnsportActivity = useBarnsportActivity;
1834
+ exports.useBarnsportMunicipalities = useBarnsportMunicipalities;
1835
+ exports.useBarnsportSitemap = useBarnsportSitemap;
1836
+ exports.useBarnsportSport = useBarnsportSport;
1837
+ exports.useBarnsportSports = useBarnsportSports;
1422
1838
  exports.useBranding = useBranding;
1839
+ exports.useCodeBallot = useCodeBallot;
1423
1840
  exports.useContent = useContent;
1424
1841
  exports.useContentItem = useContentItem;
1842
+ exports.useDocumentDownload = useDocumentDownload;
1843
+ exports.useDocuments = useDocuments;
1425
1844
  exports.useFormStats = useFormStats;
1426
1845
  exports.useForms = useForms;
1427
1846
  exports.useLinkedAccounts = useLinkedAccounts;
1428
1847
  exports.useLogo = useLogo;
1429
1848
  exports.useMedia = useMedia;
1430
1849
  exports.useMediaList = useMediaList;
1850
+ exports.useMemberDocumentDownload = useMemberDocumentDownload;
1851
+ exports.useMemberDocumentFolders = useMemberDocumentFolders;
1852
+ exports.useMemberDocuments = useMemberDocuments;
1431
1853
  exports.useModuleAccess = useModuleAccess;
1432
1854
  exports.useMySection = useMySection;
1433
1855
  exports.useNews = useNews;
1434
1856
  exports.useOrg = useOrg;
1435
1857
  exports.usePageContent = usePageContent;
1436
1858
  exports.useSections = useSections;
1859
+ exports.useSubmitBarnsportInterest = useSubmitBarnsportInterest;
1437
1860
  exports.useUpdateFormSubmission = useUpdateFormSubmission;
1438
1861
  exports.useUser = useUser;
1439
1862
  exports.userHasAllPermissions = userHasAllPermissions;