@hartl-services/medusa-affiliate 0.4.0 → 0.5.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.
@@ -1375,252 +1375,6 @@ const config$6 = adminSdk.defineRouteConfig({
1375
1375
  label: texts.routes.affiliates,
1376
1376
  rank: 81
1377
1377
  });
1378
- const useAffiliateApplications = (params) => reactQuery.useQuery({
1379
- queryKey: affiliateKeys.applicationList(params),
1380
- queryFn: () => listAffiliateApplications({
1381
- status: params.status || void 0,
1382
- limit: params.limit,
1383
- offset: params.offset
1384
- })
1385
- });
1386
- const useApproveAffiliateApplication = (applicationId) => {
1387
- const queryClient = reactQuery.useQueryClient();
1388
- return reactQuery.useMutation({
1389
- mutationFn: (payload) => {
1390
- if (!applicationId) {
1391
- throw new Error(texts.hooks.noApplicationSelected);
1392
- }
1393
- return approveAffiliateApplication(applicationId, payload);
1394
- },
1395
- onSuccess: async () => {
1396
- await queryClient.invalidateQueries({
1397
- queryKey: affiliateKeys.applications()
1398
- });
1399
- await queryClient.invalidateQueries({ queryKey: affiliateKeys.lists() });
1400
- }
1401
- });
1402
- };
1403
- const useRejectAffiliateApplication = (applicationId) => {
1404
- const queryClient = reactQuery.useQueryClient();
1405
- return reactQuery.useMutation({
1406
- mutationFn: (payload) => {
1407
- if (!applicationId) {
1408
- throw new Error(texts.hooks.noApplicationSelected);
1409
- }
1410
- return rejectAffiliateApplication(applicationId, payload);
1411
- },
1412
- onSuccess: async () => {
1413
- await queryClient.invalidateQueries({
1414
- queryKey: affiliateKeys.applications()
1415
- });
1416
- await queryClient.invalidateQueries({ queryKey: affiliateKeys.lists() });
1417
- }
1418
- });
1419
- };
1420
- const PercentRateInput = ({
1421
- label,
1422
- value,
1423
- onChange
1424
- }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
1425
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: label }),
1426
- /* @__PURE__ */ jsxRuntime.jsx(
1427
- ui.Input,
1428
- {
1429
- min: 0,
1430
- max: 100,
1431
- step: "0.01",
1432
- type: "number",
1433
- value,
1434
- onChange: (event) => onChange(Number(event.target.value))
1435
- }
1436
- )
1437
- ] });
1438
- const DEFAULT_COMMISSION_RATE = 10;
1439
- const DEFAULT_OWN_ORDER_DISCOUNT_RATE = 0;
1440
- const APPLICATIONS_PAGE_SIZE = 20;
1441
- const ApplicationsTable = ({
1442
- applications,
1443
- onSelect
1444
- }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
1445
- /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-ui-border-base border-b", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-ui-fg-subtle", children: [
1446
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.applicant }),
1447
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.customer }),
1448
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.slug }),
1449
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.submitted }),
1450
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 text-right font-medium", children: texts.applications.columns.action })
1451
- ] }) }),
1452
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: applications.map((application) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-ui-border-base border-b", children: [
1453
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3 font-medium", children: application.display_name }),
1454
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3 font-mono text-xs", children: application.customer_id }),
1455
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3", children: application.requested_slug ?? texts.common.dash }),
1456
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3", children: formatDateTime(application.created_at) }),
1457
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: () => onSelect(application), children: texts.applications.review }) })
1458
- ] }, application.id)) })
1459
- ] }) });
1460
- const AffiliateApplicationsPage = () => {
1461
- const [offset, setOffset] = react.useState(0);
1462
- const [selected, setSelected] = react.useState(null);
1463
- const [commissionRate, setCommissionRate] = react.useState(DEFAULT_COMMISSION_RATE);
1464
- const [ownOrderDiscountRate, setOwnOrderDiscountRate] = react.useState(DEFAULT_OWN_ORDER_DISCOUNT_RATE);
1465
- const [slug, setSlug] = react.useState("");
1466
- const [rejectionReason, setRejectionReason] = react.useState("");
1467
- const applicationsQuery = useAffiliateApplications({
1468
- status: "pending",
1469
- limit: APPLICATIONS_PAGE_SIZE,
1470
- offset
1471
- });
1472
- const approveMutation = useApproveAffiliateApplication(selected?.id);
1473
- const rejectMutation = useRejectAffiliateApplication(selected?.id);
1474
- const reviewPending = approveMutation.isPending || rejectMutation.isPending;
1475
- const applications = applicationsQuery.data?.applications ?? [];
1476
- const count = applicationsQuery.data?.count ?? 0;
1477
- const showPagination = !applicationsQuery.isLoading && !applicationsQuery.isError && count > 0;
1478
- const selectApplication = (application) => {
1479
- setSelected(application);
1480
- setSlug(application.requested_slug ?? "");
1481
- setRejectionReason(application.rejection_reason ?? "");
1482
- setCommissionRate(DEFAULT_COMMISSION_RATE);
1483
- setOwnOrderDiscountRate(DEFAULT_OWN_ORDER_DISCOUNT_RATE);
1484
- };
1485
- const approve = (event) => {
1486
- event.preventDefault();
1487
- approveMutation.mutate(
1488
- {
1489
- commission_rate: commissionRate,
1490
- own_order_discount_rate: ownOrderDiscountRate,
1491
- slug: slug || selected?.requested_slug || null
1492
- },
1493
- {
1494
- onSuccess: () => {
1495
- ui.toast.success(texts.applications.toasts.approved);
1496
- setSelected(null);
1497
- },
1498
- onError: (error) => ui.toast.error(texts.applications.toasts.approveFailed, {
1499
- description: getErrorMessage(error)
1500
- })
1501
- }
1502
- );
1503
- };
1504
- const reject = (event) => {
1505
- event.preventDefault();
1506
- rejectMutation.mutate(
1507
- { rejection_reason: rejectionReason || null },
1508
- {
1509
- onSuccess: () => {
1510
- ui.toast.success(texts.applications.toasts.rejected);
1511
- setSelected(null);
1512
- setRejectionReason("");
1513
- },
1514
- onError: (error) => ui.toast.error(texts.applications.toasts.rejectFailed, {
1515
- description: getErrorMessage(error)
1516
- })
1517
- }
1518
- );
1519
- };
1520
- const renderBody = () => {
1521
- if (applicationsQuery.isLoading) {
1522
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.loading }) });
1523
- }
1524
- if (applicationsQuery.isError) {
1525
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.loadError(getErrorMessage(applicationsQuery.error)) }) });
1526
- }
1527
- if (!applications.length) {
1528
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.empty }) });
1529
- }
1530
- return /* @__PURE__ */ jsxRuntime.jsx(ApplicationsTable, { applications, onSelect: selectApplication });
1531
- };
1532
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6", children: [
1533
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
1534
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between gap-4 px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1535
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: texts.applications.heading }),
1536
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.description })
1537
- ] }) }),
1538
- renderBody(),
1539
- showPagination ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
1540
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle text-sm", children: texts.common.pageRange(offset + 1, offset + applications.length, count) }),
1541
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
1542
- /* @__PURE__ */ jsxRuntime.jsx(
1543
- ui.Button,
1544
- {
1545
- size: "small",
1546
- variant: "secondary",
1547
- disabled: offset === 0,
1548
- onClick: () => setOffset((current) => Math.max(0, current - APPLICATIONS_PAGE_SIZE)),
1549
- children: texts.common.back
1550
- }
1551
- ),
1552
- /* @__PURE__ */ jsxRuntime.jsx(
1553
- ui.Button,
1554
- {
1555
- size: "small",
1556
- variant: "secondary",
1557
- disabled: offset + applications.length >= count,
1558
- onClick: () => setOffset((current) => current + APPLICATIONS_PAGE_SIZE),
1559
- children: texts.common.next
1560
- }
1561
- )
1562
- ] })
1563
- ] }) : null
1564
- ] }),
1565
- selected ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
1566
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4", children: [
1567
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: texts.applications.reviewHeading(selected.display_name) }),
1568
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-subtle", children: [
1569
- texts.applications.customerLine(selected.customer_id),
1570
- selected.message ? ` · ${selected.message}` : ""
1571
- ] })
1572
- ] }),
1573
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-5 px-6 py-5 lg:grid-cols-2", children: [
1574
- /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: approve, className: "grid gap-4", children: [
1575
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: texts.applications.approveHeading }),
1576
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
1577
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: texts.applications.affiliateSlugLabel }),
1578
- /* @__PURE__ */ jsxRuntime.jsx(
1579
- ui.Input,
1580
- {
1581
- value: slug,
1582
- onChange: (event) => setSlug(event.target.value),
1583
- placeholder: texts.applications.affiliateSlugPlaceholder
1584
- }
1585
- )
1586
- ] }),
1587
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
1588
- /* @__PURE__ */ jsxRuntime.jsx(
1589
- PercentRateInput,
1590
- {
1591
- label: texts.applications.commissionLabel,
1592
- value: commissionRate,
1593
- onChange: setCommissionRate
1594
- }
1595
- ),
1596
- /* @__PURE__ */ jsxRuntime.jsx(
1597
- PercentRateInput,
1598
- {
1599
- label: texts.applications.ownDiscountLabel,
1600
- value: ownOrderDiscountRate,
1601
- onChange: setOwnOrderDiscountRate
1602
- }
1603
- )
1604
- ] }),
1605
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", disabled: reviewPending, children: approveMutation.isPending ? texts.applications.approving : texts.applications.approve }) })
1606
- ] }),
1607
- /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: reject, className: "grid gap-4", children: [
1608
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: texts.applications.rejectHeading }),
1609
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
1610
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: texts.applications.reasonLabel }),
1611
- /* @__PURE__ */ jsxRuntime.jsx(ui.Textarea, { value: rejectionReason, onChange: (event) => setRejectionReason(event.target.value) })
1612
- ] }),
1613
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", variant: "danger", disabled: reviewPending, children: rejectMutation.isPending ? texts.applications.rejecting : texts.applications.reject }) })
1614
- ] })
1615
- ] })
1616
- ] }) : null
1617
- ] });
1618
- };
1619
- const AffiliateApplicationsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(AffiliateApplicationsPage, {});
1620
- const config$5 = adminSdk.defineRouteConfig({
1621
- label: texts.routes.applications,
1622
- rank: 80
1623
- });
1624
1378
  const getCustomerLabel = (customer) => {
1625
1379
  const name = [customer.first_name, customer.last_name].filter(Boolean).join(" ");
1626
1380
  return name ? `${name} (${customer.email})` : customer.email;
@@ -2451,6 +2205,24 @@ const AffiliateCouponPanel = ({ affiliateId }) => {
2451
2205
  )
2452
2206
  ] });
2453
2207
  };
2208
+ const PercentRateInput = ({
2209
+ label,
2210
+ value,
2211
+ onChange
2212
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
2213
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: label }),
2214
+ /* @__PURE__ */ jsxRuntime.jsx(
2215
+ ui.Input,
2216
+ {
2217
+ min: 0,
2218
+ max: 100,
2219
+ step: "0.01",
2220
+ type: "number",
2221
+ value,
2222
+ onChange: (event) => onChange(Number(event.target.value))
2223
+ }
2224
+ )
2225
+ ] });
2454
2226
  const SlugTable = ({
2455
2227
  affiliateId,
2456
2228
  slugs
@@ -2852,6 +2624,234 @@ const AffiliateEditRoute = () => {
2852
2624
  const { id } = reactRouterDom.useParams();
2853
2625
  return /* @__PURE__ */ jsxRuntime.jsx(AffiliateFormPage, { mode: "edit", affiliateId: id });
2854
2626
  };
2627
+ const useAffiliateApplications = (params) => reactQuery.useQuery({
2628
+ queryKey: affiliateKeys.applicationList(params),
2629
+ queryFn: () => listAffiliateApplications({
2630
+ status: params.status || void 0,
2631
+ limit: params.limit,
2632
+ offset: params.offset
2633
+ })
2634
+ });
2635
+ const useApproveAffiliateApplication = (applicationId) => {
2636
+ const queryClient = reactQuery.useQueryClient();
2637
+ return reactQuery.useMutation({
2638
+ mutationFn: (payload) => {
2639
+ if (!applicationId) {
2640
+ throw new Error(texts.hooks.noApplicationSelected);
2641
+ }
2642
+ return approveAffiliateApplication(applicationId, payload);
2643
+ },
2644
+ onSuccess: async () => {
2645
+ await queryClient.invalidateQueries({
2646
+ queryKey: affiliateKeys.applications()
2647
+ });
2648
+ await queryClient.invalidateQueries({ queryKey: affiliateKeys.lists() });
2649
+ }
2650
+ });
2651
+ };
2652
+ const useRejectAffiliateApplication = (applicationId) => {
2653
+ const queryClient = reactQuery.useQueryClient();
2654
+ return reactQuery.useMutation({
2655
+ mutationFn: (payload) => {
2656
+ if (!applicationId) {
2657
+ throw new Error(texts.hooks.noApplicationSelected);
2658
+ }
2659
+ return rejectAffiliateApplication(applicationId, payload);
2660
+ },
2661
+ onSuccess: async () => {
2662
+ await queryClient.invalidateQueries({
2663
+ queryKey: affiliateKeys.applications()
2664
+ });
2665
+ await queryClient.invalidateQueries({ queryKey: affiliateKeys.lists() });
2666
+ }
2667
+ });
2668
+ };
2669
+ const DEFAULT_COMMISSION_RATE = 10;
2670
+ const DEFAULT_OWN_ORDER_DISCOUNT_RATE = 0;
2671
+ const APPLICATIONS_PAGE_SIZE = 20;
2672
+ const ApplicationsTable = ({
2673
+ applications,
2674
+ onSelect
2675
+ }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left text-sm", children: [
2676
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "border-ui-border-base border-b", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-ui-fg-subtle", children: [
2677
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.applicant }),
2678
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.customer }),
2679
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.slug }),
2680
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 font-medium", children: texts.applications.columns.submitted }),
2681
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 text-right font-medium", children: texts.applications.columns.action })
2682
+ ] }) }),
2683
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: applications.map((application) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-ui-border-base border-b", children: [
2684
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3 font-medium", children: application.display_name }),
2685
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3 font-mono text-xs", children: application.customer_id }),
2686
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3", children: application.requested_slug ?? texts.common.dash }),
2687
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3", children: formatDateTime(application.created_at) }),
2688
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: () => onSelect(application), children: texts.applications.review }) })
2689
+ ] }, application.id)) })
2690
+ ] }) });
2691
+ const AffiliateApplicationsPage = () => {
2692
+ const [offset, setOffset] = react.useState(0);
2693
+ const [selected, setSelected] = react.useState(null);
2694
+ const [commissionRate, setCommissionRate] = react.useState(DEFAULT_COMMISSION_RATE);
2695
+ const [ownOrderDiscountRate, setOwnOrderDiscountRate] = react.useState(DEFAULT_OWN_ORDER_DISCOUNT_RATE);
2696
+ const [slug, setSlug] = react.useState("");
2697
+ const [rejectionReason, setRejectionReason] = react.useState("");
2698
+ const applicationsQuery = useAffiliateApplications({
2699
+ status: "pending",
2700
+ limit: APPLICATIONS_PAGE_SIZE,
2701
+ offset
2702
+ });
2703
+ const approveMutation = useApproveAffiliateApplication(selected?.id);
2704
+ const rejectMutation = useRejectAffiliateApplication(selected?.id);
2705
+ const reviewPending = approveMutation.isPending || rejectMutation.isPending;
2706
+ const applications = applicationsQuery.data?.applications ?? [];
2707
+ const count = applicationsQuery.data?.count ?? 0;
2708
+ const showPagination = !applicationsQuery.isLoading && !applicationsQuery.isError && count > 0;
2709
+ const selectApplication = (application) => {
2710
+ setSelected(application);
2711
+ setSlug(application.requested_slug ?? "");
2712
+ setRejectionReason(application.rejection_reason ?? "");
2713
+ setCommissionRate(DEFAULT_COMMISSION_RATE);
2714
+ setOwnOrderDiscountRate(DEFAULT_OWN_ORDER_DISCOUNT_RATE);
2715
+ };
2716
+ const approve = (event) => {
2717
+ event.preventDefault();
2718
+ approveMutation.mutate(
2719
+ {
2720
+ commission_rate: commissionRate,
2721
+ own_order_discount_rate: ownOrderDiscountRate,
2722
+ slug: slug || selected?.requested_slug || null
2723
+ },
2724
+ {
2725
+ onSuccess: () => {
2726
+ ui.toast.success(texts.applications.toasts.approved);
2727
+ setSelected(null);
2728
+ },
2729
+ onError: (error) => ui.toast.error(texts.applications.toasts.approveFailed, {
2730
+ description: getErrorMessage(error)
2731
+ })
2732
+ }
2733
+ );
2734
+ };
2735
+ const reject = (event) => {
2736
+ event.preventDefault();
2737
+ rejectMutation.mutate(
2738
+ { rejection_reason: rejectionReason || null },
2739
+ {
2740
+ onSuccess: () => {
2741
+ ui.toast.success(texts.applications.toasts.rejected);
2742
+ setSelected(null);
2743
+ setRejectionReason("");
2744
+ },
2745
+ onError: (error) => ui.toast.error(texts.applications.toasts.rejectFailed, {
2746
+ description: getErrorMessage(error)
2747
+ })
2748
+ }
2749
+ );
2750
+ };
2751
+ const renderBody = () => {
2752
+ if (applicationsQuery.isLoading) {
2753
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.loading }) });
2754
+ }
2755
+ if (applicationsQuery.isError) {
2756
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.loadError(getErrorMessage(applicationsQuery.error)) }) });
2757
+ }
2758
+ if (!applications.length) {
2759
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.empty }) });
2760
+ }
2761
+ return /* @__PURE__ */ jsxRuntime.jsx(ApplicationsTable, { applications, onSelect: selectApplication });
2762
+ };
2763
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-6", children: [
2764
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
2765
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between gap-4 px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2766
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: texts.applications.heading }),
2767
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: texts.applications.description })
2768
+ ] }) }),
2769
+ renderBody(),
2770
+ showPagination ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
2771
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle text-sm", children: texts.common.pageRange(offset + 1, offset + applications.length, count) }),
2772
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
2773
+ /* @__PURE__ */ jsxRuntime.jsx(
2774
+ ui.Button,
2775
+ {
2776
+ size: "small",
2777
+ variant: "secondary",
2778
+ disabled: offset === 0,
2779
+ onClick: () => setOffset((current) => Math.max(0, current - APPLICATIONS_PAGE_SIZE)),
2780
+ children: texts.common.back
2781
+ }
2782
+ ),
2783
+ /* @__PURE__ */ jsxRuntime.jsx(
2784
+ ui.Button,
2785
+ {
2786
+ size: "small",
2787
+ variant: "secondary",
2788
+ disabled: offset + applications.length >= count,
2789
+ onClick: () => setOffset((current) => current + APPLICATIONS_PAGE_SIZE),
2790
+ children: texts.common.next
2791
+ }
2792
+ )
2793
+ ] })
2794
+ ] }) : null
2795
+ ] }),
2796
+ selected ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
2797
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4", children: [
2798
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: texts.applications.reviewHeading(selected.display_name) }),
2799
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-subtle", children: [
2800
+ texts.applications.customerLine(selected.customer_id),
2801
+ selected.message ? ` · ${selected.message}` : ""
2802
+ ] })
2803
+ ] }),
2804
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-5 px-6 py-5 lg:grid-cols-2", children: [
2805
+ /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: approve, className: "grid gap-4", children: [
2806
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: texts.applications.approveHeading }),
2807
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
2808
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: texts.applications.affiliateSlugLabel }),
2809
+ /* @__PURE__ */ jsxRuntime.jsx(
2810
+ ui.Input,
2811
+ {
2812
+ value: slug,
2813
+ onChange: (event) => setSlug(event.target.value),
2814
+ placeholder: texts.applications.affiliateSlugPlaceholder
2815
+ }
2816
+ )
2817
+ ] }),
2818
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
2819
+ /* @__PURE__ */ jsxRuntime.jsx(
2820
+ PercentRateInput,
2821
+ {
2822
+ label: texts.applications.commissionLabel,
2823
+ value: commissionRate,
2824
+ onChange: setCommissionRate
2825
+ }
2826
+ ),
2827
+ /* @__PURE__ */ jsxRuntime.jsx(
2828
+ PercentRateInput,
2829
+ {
2830
+ label: texts.applications.ownDiscountLabel,
2831
+ value: ownOrderDiscountRate,
2832
+ onChange: setOwnOrderDiscountRate
2833
+ }
2834
+ )
2835
+ ] }),
2836
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", disabled: reviewPending, children: approveMutation.isPending ? texts.applications.approving : texts.applications.approve }) })
2837
+ ] }),
2838
+ /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: reject, className: "grid gap-4", children: [
2839
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: texts.applications.rejectHeading }),
2840
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
2841
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { children: texts.applications.reasonLabel }),
2842
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Textarea, { value: rejectionReason, onChange: (event) => setRejectionReason(event.target.value) })
2843
+ ] }),
2844
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", variant: "danger", disabled: reviewPending, children: rejectMutation.isPending ? texts.applications.rejecting : texts.applications.reject }) })
2845
+ ] })
2846
+ ] })
2847
+ ] }) : null
2848
+ ] });
2849
+ };
2850
+ const AffiliateApplicationsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(AffiliateApplicationsPage, {});
2851
+ const config$5 = adminSdk.defineRouteConfig({
2852
+ label: texts.routes.applications,
2853
+ rank: 80
2854
+ });
2855
2855
  function ConsignmentReportsPage() {
2856
2856
  const reports = reactQuery.useQuery({
2857
2857
  queryKey: ["affiliate", "consignment-reports"],
@@ -3615,15 +3615,15 @@ const routeModule = {
3615
3615
  path: "/affiliates",
3616
3616
  handle: { label: config$6.label, translationNs: config$6.translationNs }
3617
3617
  },
3618
+ {
3619
+ Component: AffiliateEditRoute,
3620
+ path: "/affiliates/:id"
3621
+ },
3618
3622
  {
3619
3623
  Component: AffiliateApplicationsRoute,
3620
3624
  path: "/affiliates/applications",
3621
3625
  handle: { label: config$5.label, translationNs: config$5.translationNs }
3622
3626
  },
3623
- {
3624
- Component: AffiliateEditRoute,
3625
- path: "/affiliates/:id"
3626
- },
3627
3627
  {
3628
3628
  Component: ConsignmentReportsRoute,
3629
3629
  path: "/affiliates/consignment-reports",