@infuro/cms-core 1.0.50 → 1.0.52
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/admin.cjs +843 -402
- package/dist/admin.d.cts +13 -1
- package/dist/admin.d.ts +13 -1
- package/dist/admin.js +843 -402
- package/dist/api.cjs +35 -35
- package/dist/api.js +4 -4
- package/dist/auth.cjs +44 -43
- package/dist/auth.d.cts +2 -3
- package/dist/auth.d.ts +2 -3
- package/dist/auth.js +2 -1
- package/dist/{chunk-JCMOOPNX.cjs → chunk-3BPD5NGU.cjs} +210 -90
- package/dist/chunk-7L6KWI7S.cjs +212 -0
- package/dist/{chunk-YV5PK4JW.cjs → chunk-BC22I7C7.cjs} +45 -247
- package/dist/{chunk-WRKV6MHB.js → chunk-BNKZNLEX.js} +2 -196
- package/dist/{chunk-IPDHT2UV.js → chunk-CTXBYO2J.js} +94 -104
- package/dist/{chunk-UUWAUHUW.cjs → chunk-JN4AFHZ4.cjs} +94 -105
- package/dist/{chunk-JE22VP6S.js → chunk-MXIWUFBP.js} +1 -1
- package/dist/{chunk-LT2WOPKA.js → chunk-UO5Q5RXB.js} +181 -61
- package/dist/{chunk-KOTXDSQB.cjs → chunk-UQWZUZ5X.cjs} +1 -1
- package/dist/chunk-WUQAOTHA.js +203 -0
- package/dist/{emit-order-notification-trigger-6XX7LSC4.js → emit-order-notification-trigger-HZQPPSFB.js} +1 -1
- package/dist/{emit-order-notification-trigger-NASG7ZEO.cjs → emit-order-notification-trigger-NR3VN6C6.cjs} +3 -3
- package/dist/index.cjs +334 -299
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +59 -24
- package/dist/middleware.cjs +15 -0
- package/dist/middleware.js +2 -0
- package/dist/{order-notification-dispatcher-3TA4ETYJ.js → order-notification-dispatcher-AT4IFAGL.js} +2 -2
- package/dist/{order-notification-dispatcher-ZEAZ5SHV.cjs → order-notification-dispatcher-YBAWDOIO.cjs} +5 -5
- package/package.json +6 -1
package/dist/admin.cjs
CHANGED
|
@@ -26,10 +26,10 @@ require('jodit/es2021/jodit.min.css');
|
|
|
26
26
|
var chart_js = require('chart.js');
|
|
27
27
|
var reactChartjs2 = require('react-chartjs-2');
|
|
28
28
|
var CheckboxPrimitive = require('@radix-ui/react-checkbox');
|
|
29
|
+
var countryStateCity = require('country-state-city');
|
|
29
30
|
var reactQrCode = require('react-qr-code');
|
|
30
31
|
require('typeorm');
|
|
31
32
|
var core = require('@craftjs/core');
|
|
32
|
-
var countryStateCity = require('country-state-city');
|
|
33
33
|
var nextThemes = require('next-themes');
|
|
34
34
|
|
|
35
35
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -264,11 +264,20 @@ var init_infuro_favicon = __esm({
|
|
|
264
264
|
function isSuperAdminGroupName(name) {
|
|
265
265
|
return name === ADMIN_GROUP_NAME;
|
|
266
266
|
}
|
|
267
|
+
function hasEntityPermission(record, entity, action) {
|
|
268
|
+
const p = record?.[entity];
|
|
269
|
+
if (!p) return false;
|
|
270
|
+
if (action === "create") return p.c;
|
|
271
|
+
if (action === "read") return p.r;
|
|
272
|
+
if (action === "update") return p.u;
|
|
273
|
+
return p.d;
|
|
274
|
+
}
|
|
267
275
|
var ADMIN_GROUP_NAME;
|
|
268
276
|
var init_permission_entities = __esm({
|
|
269
277
|
"src/auth/permission-entities.ts"() {
|
|
270
278
|
ADMIN_GROUP_NAME = "Administrator";
|
|
271
279
|
__name(isSuperAdminGroupName, "isSuperAdminGroupName");
|
|
280
|
+
__name(hasEntityPermission, "hasEntityPermission");
|
|
272
281
|
}
|
|
273
282
|
});
|
|
274
283
|
|
|
@@ -470,6 +479,395 @@ var init_Header = __esm({
|
|
|
470
479
|
__name(AdminHeader, "AdminHeader");
|
|
471
480
|
}
|
|
472
481
|
});
|
|
482
|
+
|
|
483
|
+
// src/lib/vendor-role-defaults.ts
|
|
484
|
+
function full() {
|
|
485
|
+
return {
|
|
486
|
+
canCreate: true,
|
|
487
|
+
canRead: true,
|
|
488
|
+
canUpdate: true,
|
|
489
|
+
canDelete: true
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
function read() {
|
|
493
|
+
return {
|
|
494
|
+
canCreate: false,
|
|
495
|
+
canRead: true,
|
|
496
|
+
canUpdate: false,
|
|
497
|
+
canDelete: false
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
function none() {
|
|
501
|
+
return {
|
|
502
|
+
canCreate: false,
|
|
503
|
+
canRead: false,
|
|
504
|
+
canUpdate: false,
|
|
505
|
+
canDelete: false
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function readUpdate() {
|
|
509
|
+
return {
|
|
510
|
+
canCreate: false,
|
|
511
|
+
canRead: true,
|
|
512
|
+
canUpdate: true,
|
|
513
|
+
canDelete: false
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
function storePerms(spec) {
|
|
517
|
+
const resolve = /* @__PURE__ */ __name((v) => {
|
|
518
|
+
if (v === "full") return full();
|
|
519
|
+
if (v === "read") return read();
|
|
520
|
+
if (v === "none") return none();
|
|
521
|
+
return v;
|
|
522
|
+
}, "resolve");
|
|
523
|
+
const out = {};
|
|
524
|
+
for (const entity of STORE_ENTITIES) {
|
|
525
|
+
out[entity] = resolve(spec[entity] ?? "none");
|
|
526
|
+
}
|
|
527
|
+
return out;
|
|
528
|
+
}
|
|
529
|
+
var VENDOR_RBAC_ENTITIES, STORE_ENTITIES;
|
|
530
|
+
var init_vendor_role_defaults = __esm({
|
|
531
|
+
"src/lib/vendor-role-defaults.ts"() {
|
|
532
|
+
init_vendor_scope();
|
|
533
|
+
VENDOR_RBAC_ENTITIES = [
|
|
534
|
+
...VENDOR_STORE_RBAC_ENTITIES,
|
|
535
|
+
"dashboard",
|
|
536
|
+
"settings",
|
|
537
|
+
"team",
|
|
538
|
+
"roles"
|
|
539
|
+
];
|
|
540
|
+
STORE_ENTITIES = [
|
|
541
|
+
...VENDOR_STORE_RBAC_ENTITIES
|
|
542
|
+
];
|
|
543
|
+
__name(full, "full");
|
|
544
|
+
__name(read, "read");
|
|
545
|
+
__name(none, "none");
|
|
546
|
+
__name(readUpdate, "readUpdate");
|
|
547
|
+
__name(storePerms, "storePerms");
|
|
548
|
+
[
|
|
549
|
+
{
|
|
550
|
+
name: "Owner",
|
|
551
|
+
description: "Full store access and team/role management",
|
|
552
|
+
isSystem: true,
|
|
553
|
+
isOwnerRole: true,
|
|
554
|
+
permissions: {
|
|
555
|
+
...storePerms(Object.fromEntries(STORE_ENTITIES.map((e) => [
|
|
556
|
+
e,
|
|
557
|
+
"full"
|
|
558
|
+
]))),
|
|
559
|
+
dashboard: read(),
|
|
560
|
+
settings: readUpdate(),
|
|
561
|
+
team: full(),
|
|
562
|
+
roles: full()
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
name: "Manager",
|
|
567
|
+
description: "Day-to-day store operations",
|
|
568
|
+
isSystem: true,
|
|
569
|
+
isOwnerRole: false,
|
|
570
|
+
permissions: {
|
|
571
|
+
...storePerms({
|
|
572
|
+
products: "full",
|
|
573
|
+
collections: "full",
|
|
574
|
+
brands: "full",
|
|
575
|
+
product_categories: "full",
|
|
576
|
+
orders: "full",
|
|
577
|
+
vendor_customers: "full",
|
|
578
|
+
discounts: "full",
|
|
579
|
+
order_discounts: "full",
|
|
580
|
+
order_addresses: "full",
|
|
581
|
+
payments: "read",
|
|
582
|
+
taxes: "read",
|
|
583
|
+
attributes: "read"
|
|
584
|
+
}),
|
|
585
|
+
dashboard: read(),
|
|
586
|
+
settings: read(),
|
|
587
|
+
team: none(),
|
|
588
|
+
roles: none()
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
name: "Catalog Staff",
|
|
593
|
+
description: "Manage products and catalog content",
|
|
594
|
+
isSystem: true,
|
|
595
|
+
isOwnerRole: false,
|
|
596
|
+
permissions: {
|
|
597
|
+
...storePerms({
|
|
598
|
+
products: "full",
|
|
599
|
+
collections: "full",
|
|
600
|
+
brands: "full",
|
|
601
|
+
product_categories: "full",
|
|
602
|
+
attributes: "full",
|
|
603
|
+
orders: "read",
|
|
604
|
+
vendor_customers: "read"
|
|
605
|
+
}),
|
|
606
|
+
dashboard: read(),
|
|
607
|
+
settings: none(),
|
|
608
|
+
team: none(),
|
|
609
|
+
roles: none()
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
name: "Fulfillment",
|
|
614
|
+
description: "Orders and fulfillment",
|
|
615
|
+
isSystem: true,
|
|
616
|
+
isOwnerRole: false,
|
|
617
|
+
permissions: {
|
|
618
|
+
...storePerms({
|
|
619
|
+
products: "read",
|
|
620
|
+
orders: "full",
|
|
621
|
+
order_addresses: "full",
|
|
622
|
+
order_discounts: "read",
|
|
623
|
+
vendor_customers: "read"
|
|
624
|
+
}),
|
|
625
|
+
dashboard: read(),
|
|
626
|
+
settings: none(),
|
|
627
|
+
team: none(),
|
|
628
|
+
roles: none()
|
|
629
|
+
}
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
name: "Viewer",
|
|
633
|
+
description: "Read-only access to store data",
|
|
634
|
+
isSystem: true,
|
|
635
|
+
isOwnerRole: false,
|
|
636
|
+
permissions: {
|
|
637
|
+
...storePerms(Object.fromEntries(STORE_ENTITIES.map((e) => [
|
|
638
|
+
e,
|
|
639
|
+
"read"
|
|
640
|
+
]))),
|
|
641
|
+
dashboard: read(),
|
|
642
|
+
settings: none(),
|
|
643
|
+
team: none(),
|
|
644
|
+
roles: none()
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
];
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
// src/auth/rbac-debug.ts
|
|
652
|
+
function summarizeEntityPerms(entityPerms) {
|
|
653
|
+
const out = {};
|
|
654
|
+
if (!entityPerms) return out;
|
|
655
|
+
for (const [entity, p] of Object.entries(entityPerms)) {
|
|
656
|
+
out[entity] = {
|
|
657
|
+
c: p.c,
|
|
658
|
+
r: p.r,
|
|
659
|
+
u: p.u,
|
|
660
|
+
d: p.d
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
return out;
|
|
664
|
+
}
|
|
665
|
+
function vendorPortalFallbackReason(user, entity, action) {
|
|
666
|
+
if (!isVendorPortalUser(user)) return null;
|
|
667
|
+
if (entity === "dashboard" && action === "read") return "vendor_portal_dashboard_fallback";
|
|
668
|
+
if (entity === "analytics" && action === "read") return "vendor_portal_analytics_fallback";
|
|
669
|
+
if (entity === "settings" && action === "read") return "vendor_portal_settings_read_fallback";
|
|
670
|
+
if (entity === "upload" && (action === "create" || action === "read")) {
|
|
671
|
+
return "vendor_portal_upload_fallback";
|
|
672
|
+
}
|
|
673
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity) && action === "read") return "vendor_portal_store_read_fallback";
|
|
674
|
+
return null;
|
|
675
|
+
}
|
|
676
|
+
function explainSessionEntityAccess(user, entity, action) {
|
|
677
|
+
const userSnapshot = {
|
|
678
|
+
email: user?.email ?? null,
|
|
679
|
+
id: user?.id ?? null,
|
|
680
|
+
groupId: user?.groupId ?? null,
|
|
681
|
+
groupName: user?.groupName ?? null,
|
|
682
|
+
isRBACAdmin: user?.isRBACAdmin ?? false,
|
|
683
|
+
adminAccess: user?.adminAccess ?? null,
|
|
684
|
+
vendorIds: user?.vendorIds ?? [],
|
|
685
|
+
activeVendorId: user?.activeVendorId ?? null,
|
|
686
|
+
vendorRole: user?.vendorRole ?? null,
|
|
687
|
+
vendorRoleId: user?.vendorRoleId ?? null,
|
|
688
|
+
vendorRoleName: user?.vendorRoleName ?? null,
|
|
689
|
+
isVendorRoleOwner: user?.isVendorRoleOwner ?? false,
|
|
690
|
+
vendorEntityPerms: summarizeEntityPerms(user?.vendorEntityPerms),
|
|
691
|
+
isVendorPortal: user?.isVendorPortal ?? false,
|
|
692
|
+
isVendorOwner: user?.isVendorOwner ?? false,
|
|
693
|
+
isVendorPortalComputed: isVendorPortalUser(user),
|
|
694
|
+
isVendorOwnerComputed: isVendorOwner(user),
|
|
695
|
+
jwtEntityPerms: summarizeEntityPerms(user?.entityPerms),
|
|
696
|
+
jwtEntityPermForTarget: user?.entityPerms?.[entity] ?? null
|
|
697
|
+
};
|
|
698
|
+
if (!user?.email) {
|
|
699
|
+
return {
|
|
700
|
+
allowed: false,
|
|
701
|
+
reason: "no_session_email",
|
|
702
|
+
userSnapshot
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
if (user.isRBACAdmin) {
|
|
706
|
+
return {
|
|
707
|
+
allowed: true,
|
|
708
|
+
reason: "platform_administrator",
|
|
709
|
+
userSnapshot
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
if ((isVendorPortalUser(user) || (user.vendorIds?.length ?? 0) > 0) && entity === "upload" && (action === "create" || action === "read")) {
|
|
713
|
+
return {
|
|
714
|
+
allowed: true,
|
|
715
|
+
reason: "vendor_portal_upload",
|
|
716
|
+
userSnapshot
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
const vendorIds = user.vendorIds ?? [];
|
|
720
|
+
const isStaff = user.vendorRole === "staff";
|
|
721
|
+
const vendorPerms = user.vendorEntityPerms;
|
|
722
|
+
const hasVendorRolePerms = vendorPerms != null && Object.keys(vendorPerms).length > 0;
|
|
723
|
+
const enforceVendorRoleMatrix = vendorIds.length > 0 && (hasVendorRolePerms || user.vendorRoleId != null);
|
|
724
|
+
if (enforceVendorRoleMatrix) {
|
|
725
|
+
const vendorRbacSet = new Set(VENDOR_RBAC_ENTITIES);
|
|
726
|
+
if (vendorRbacSet.has(entity) || entity === "analytics") {
|
|
727
|
+
if (entity === "analytics" && action === "read") {
|
|
728
|
+
const allowed3 = hasEntityPermission(vendorPerms, "dashboard", "read");
|
|
729
|
+
return {
|
|
730
|
+
allowed: allowed3,
|
|
731
|
+
reason: allowed3 ? "vendor_role_analytics_via_dashboard" : "vendor_role_analytics_denied",
|
|
732
|
+
userSnapshot
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
if (user.isVendorRoleOwner === true) {
|
|
736
|
+
return {
|
|
737
|
+
allowed: true,
|
|
738
|
+
reason: "vendor_owner_role_full",
|
|
739
|
+
userSnapshot
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
const allowed2 = hasEntityPermission(vendorPerms, entity, action);
|
|
743
|
+
return {
|
|
744
|
+
allowed: allowed2,
|
|
745
|
+
reason: allowed2 ? "vendor_role_permissions_allow" : "vendor_role_permissions_deny",
|
|
746
|
+
userSnapshot
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
if (vendorIds.length > 0) {
|
|
751
|
+
if (entity === "dashboard" && action === "read") {
|
|
752
|
+
return {
|
|
753
|
+
allowed: true,
|
|
754
|
+
reason: "vendor_link_dashboard_read",
|
|
755
|
+
userSnapshot
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
if (entity === "analytics" && action === "read") {
|
|
759
|
+
return {
|
|
760
|
+
allowed: true,
|
|
761
|
+
reason: "vendor_link_analytics_read",
|
|
762
|
+
userSnapshot
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
if (entity === "settings") {
|
|
766
|
+
if (action === "read") {
|
|
767
|
+
return {
|
|
768
|
+
allowed: true,
|
|
769
|
+
reason: "vendor_link_settings_read",
|
|
770
|
+
userSnapshot
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
if (action === "update" && !isStaff) {
|
|
774
|
+
return {
|
|
775
|
+
allowed: true,
|
|
776
|
+
reason: "vendor_link_settings_update",
|
|
777
|
+
userSnapshot
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
|
|
782
|
+
if (isStaff && action === "read") {
|
|
783
|
+
return {
|
|
784
|
+
allowed: true,
|
|
785
|
+
reason: "vendor_staff_store_read",
|
|
786
|
+
userSnapshot
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
if (!isStaff) {
|
|
790
|
+
return {
|
|
791
|
+
allowed: true,
|
|
792
|
+
reason: "vendor_link_store_full",
|
|
793
|
+
userSnapshot
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
return {
|
|
797
|
+
allowed: false,
|
|
798
|
+
reason: "vendor_staff_store_write_denied",
|
|
799
|
+
userSnapshot
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
if (isVendorPortalUser(user) && isVendorOwner(user)) {
|
|
804
|
+
if (entity === "dashboard" && action === "read") {
|
|
805
|
+
return {
|
|
806
|
+
allowed: true,
|
|
807
|
+
reason: "vendor_owner_group_dashboard",
|
|
808
|
+
userSnapshot
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
if (entity === "analytics" && action === "read") {
|
|
812
|
+
return {
|
|
813
|
+
allowed: true,
|
|
814
|
+
reason: "vendor_owner_group_analytics",
|
|
815
|
+
userSnapshot
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
if (entity === "settings" && (action === "read" || action === "update")) {
|
|
819
|
+
return {
|
|
820
|
+
allowed: true,
|
|
821
|
+
reason: "vendor_owner_group_settings",
|
|
822
|
+
userSnapshot
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
|
|
826
|
+
return {
|
|
827
|
+
allowed: true,
|
|
828
|
+
reason: "vendor_owner_group_store",
|
|
829
|
+
userSnapshot
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
const vendorPortalReason = vendorPortalFallbackReason(user, entity, action);
|
|
834
|
+
if (vendorPortalReason) {
|
|
835
|
+
return {
|
|
836
|
+
allowed: true,
|
|
837
|
+
reason: vendorPortalReason,
|
|
838
|
+
userSnapshot
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
const explicit = user.entityPerms?.[entity];
|
|
842
|
+
if (explicit !== void 0) {
|
|
843
|
+
const allowed2 = hasEntityPermission(user.entityPerms, entity, action);
|
|
844
|
+
return {
|
|
845
|
+
allowed: allowed2,
|
|
846
|
+
reason: allowed2 ? "jwt_entity_perms_allow" : "jwt_entity_perms_deny",
|
|
847
|
+
userSnapshot
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
const allowed = hasEntityPermission(user.entityPerms, entity, action);
|
|
851
|
+
return {
|
|
852
|
+
allowed,
|
|
853
|
+
reason: allowed ? "entity_perms_fallback_allow" : "no_matching_rule",
|
|
854
|
+
userSnapshot
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
function sessionHasEntityAccessFromExplanation(user, entity, action) {
|
|
858
|
+
return explainSessionEntityAccess(user, entity, action).allowed;
|
|
859
|
+
}
|
|
860
|
+
var init_rbac_debug = __esm({
|
|
861
|
+
"src/auth/rbac-debug.ts"() {
|
|
862
|
+
init_permission_entities();
|
|
863
|
+
init_vendor_role_defaults();
|
|
864
|
+
init_vendor_scope();
|
|
865
|
+
__name(summarizeEntityPerms, "summarizeEntityPerms");
|
|
866
|
+
__name(vendorPortalFallbackReason, "vendorPortalFallbackReason");
|
|
867
|
+
__name(explainSessionEntityAccess, "explainSessionEntityAccess");
|
|
868
|
+
__name(sessionHasEntityAccessFromExplanation, "sessionHasEntityAccessFromExplanation");
|
|
869
|
+
}
|
|
870
|
+
});
|
|
473
871
|
var defaultValue; exports.AdminConfigContext = void 0;
|
|
474
872
|
var init_admin_config_context = __esm({
|
|
475
873
|
"src/admin/admin-config-context.tsx"() {
|
|
@@ -489,7 +887,7 @@ var init_admin_config_context = __esm({
|
|
|
489
887
|
var CMS_VERSION;
|
|
490
888
|
var init_cms_version = __esm({
|
|
491
889
|
"src/lib/cms-version.ts"() {
|
|
492
|
-
CMS_VERSION = "1.0.
|
|
890
|
+
CMS_VERSION = "1.0.52" ;
|
|
493
891
|
}
|
|
494
892
|
});
|
|
495
893
|
function useCatalogCategories(enabled = true) {
|
|
@@ -624,6 +1022,10 @@ function AdminSidebar({ variant = "sidebar" }) {
|
|
|
624
1022
|
const sectionCls7 = "mb-5";
|
|
625
1023
|
const headingCls = "text-[11px] font-semibold text-gray-400 uppercase tracking-wider px-2.5 mb-1.5";
|
|
626
1024
|
const asideCls = isDrawer ? "w-full h-full min-h-0 bg-white flex flex-col overflow-hidden" : "w-52 h-full min-h-0 bg-white border-r border-gray-200 flex-shrink-0 flex flex-col overflow-hidden";
|
|
1025
|
+
const canReadEntity = /* @__PURE__ */ __name((entity) => {
|
|
1026
|
+
if (!sessionUser) return true;
|
|
1027
|
+
return sessionHasEntityAccessFromExplanation(sessionUser, entity, "read");
|
|
1028
|
+
}, "canReadEntity");
|
|
627
1029
|
return /* @__PURE__ */ React.createElement("aside", {
|
|
628
1030
|
className: asideCls
|
|
629
1031
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
@@ -641,30 +1043,40 @@ function AdminSidebar({ variant = "sidebar" }) {
|
|
|
641
1043
|
className: `${linkCls} ${isActive("/admin/dashboard") ? linkActive : linkInactive}`
|
|
642
1044
|
}, /* @__PURE__ */ React.createElement(LucideIcons.LayoutDashboard, {
|
|
643
1045
|
className: `h-4 w-4 mr-2 ${isActive("/admin/dashboard") ? iconActive : iconInactive}`
|
|
644
|
-
}), "Dashboard")))), showPlatformNav && customNavSections.length > 0 && customNavSections.map((section) =>
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
}, /* @__PURE__ */ React.createElement(
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
1046
|
+
}), "Dashboard")))), showPlatformNav && customNavSections.length > 0 && customNavSections.map((section) => {
|
|
1047
|
+
const filteredItems = section.items.filter((item) => {
|
|
1048
|
+
const entity = item.href.replace("/admin/", "").split("/")[0];
|
|
1049
|
+
return canReadEntity(entity);
|
|
1050
|
+
});
|
|
1051
|
+
if (filteredItems.length === 0) return null;
|
|
1052
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
1053
|
+
key: section.title,
|
|
1054
|
+
className: sectionCls7
|
|
1055
|
+
}, /* @__PURE__ */ React.createElement("h3", {
|
|
1056
|
+
className: headingCls
|
|
1057
|
+
}, section.title), /* @__PURE__ */ React.createElement("ul", {
|
|
1058
|
+
className: "space-y-0.5"
|
|
1059
|
+
}, filteredItems.map((item) => {
|
|
1060
|
+
const Icon2 = getIconForItem(item.icon);
|
|
1061
|
+
return /* @__PURE__ */ React.createElement("li", {
|
|
1062
|
+
key: item.href
|
|
1063
|
+
}, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1064
|
+
href: item.href,
|
|
1065
|
+
className: `${linkCls} ${isActive(item.href) ? linkActive : linkInactive}`
|
|
1066
|
+
}, /* @__PURE__ */ React.createElement(Icon2, {
|
|
1067
|
+
className: `h-4 w-4 mr-2 ${isActive(item.href) ? iconActive : iconInactive}`
|
|
1068
|
+
}), item.label));
|
|
1069
|
+
})));
|
|
1070
|
+
}), showPlatformNav && customNavSections.length === 0 && customNavItems.length > 0 && /* @__PURE__ */ React.createElement("div", {
|
|
662
1071
|
className: sectionCls7
|
|
663
1072
|
}, /* @__PURE__ */ React.createElement("h3", {
|
|
664
1073
|
className: headingCls
|
|
665
1074
|
}, "Custom"), /* @__PURE__ */ React.createElement("ul", {
|
|
666
1075
|
className: "space-y-0.5"
|
|
667
|
-
}, customNavItems.
|
|
1076
|
+
}, customNavItems.filter((item) => {
|
|
1077
|
+
const entity = item.href.replace("/admin/", "").split("/")[0];
|
|
1078
|
+
return canReadEntity(entity);
|
|
1079
|
+
}).map((item) => {
|
|
668
1080
|
const Icon2 = getIconForItem(item.icon);
|
|
669
1081
|
return /* @__PURE__ */ React.createElement("li", {
|
|
670
1082
|
key: item.href
|
|
@@ -685,85 +1097,92 @@ function AdminSidebar({ variant = "sidebar" }) {
|
|
|
685
1097
|
className: `${linkCls} ${isActive("/admin/dashboard") ? linkActive : linkInactive}`
|
|
686
1098
|
}, /* @__PURE__ */ React.createElement(LucideIcons.LayoutDashboard, {
|
|
687
1099
|
className: `h-4 w-4 mr-2 ${isActive("/admin/dashboard") ? iconActive : iconInactive}`
|
|
688
|
-
}), "Dashboard")))), vendorPortal && customNavSections.length > 0 && customNavSections.map((section) =>
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
}, /* @__PURE__ */ React.createElement(
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
1100
|
+
}), "Dashboard")))), vendorPortal && customNavSections.length > 0 && customNavSections.map((section) => {
|
|
1101
|
+
const filteredItems = section.items.filter((item) => {
|
|
1102
|
+
const entity = item.href.replace("/admin/", "").split("/")[0];
|
|
1103
|
+
return canReadEntity(entity);
|
|
1104
|
+
});
|
|
1105
|
+
if (filteredItems.length === 0) return null;
|
|
1106
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
1107
|
+
key: section.title,
|
|
1108
|
+
className: sectionCls7
|
|
1109
|
+
}, /* @__PURE__ */ React.createElement("h3", {
|
|
1110
|
+
className: headingCls
|
|
1111
|
+
}, section.title), /* @__PURE__ */ React.createElement("ul", {
|
|
1112
|
+
className: "space-y-0.5"
|
|
1113
|
+
}, filteredItems.map((item) => {
|
|
1114
|
+
const Icon2 = getIconForItem(item.icon);
|
|
1115
|
+
return /* @__PURE__ */ React.createElement("li", {
|
|
1116
|
+
key: item.href
|
|
1117
|
+
}, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1118
|
+
href: item.href,
|
|
1119
|
+
className: `${linkCls} ${isActive(item.href) ? linkActive : linkInactive}`
|
|
1120
|
+
}, /* @__PURE__ */ React.createElement(Icon2, {
|
|
1121
|
+
className: `h-4 w-4 mr-2 ${isActive(item.href) ? iconActive : iconInactive}`
|
|
1122
|
+
}), item.label));
|
|
1123
|
+
})));
|
|
1124
|
+
}), showStoreNav && /* @__PURE__ */ React.createElement("div", {
|
|
706
1125
|
className: sectionCls7
|
|
707
1126
|
}, /* @__PURE__ */ React.createElement("h3", {
|
|
708
1127
|
className: headingCls
|
|
709
1128
|
}, "Store"), /* @__PURE__ */ React.createElement("ul", {
|
|
710
1129
|
className: "space-y-0.5"
|
|
711
|
-
}, showVendorOnboard && multiVendorEnabled !== false && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1130
|
+
}, showVendorOnboard && multiVendorEnabled !== false && canReadEntity("vendors") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
712
1131
|
href: "/admin/vendors",
|
|
713
1132
|
className: `${linkCls} ${isActive("/admin/vendors") ? linkActive : linkInactive}`
|
|
714
1133
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Store, {
|
|
715
1134
|
className: `h-4 w-4 mr-2 ${isActive("/admin/vendors") ? iconActive : iconInactive}`
|
|
716
|
-
}), "Vendors")), showVendorCategories && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1135
|
+
}), "Vendors")), showVendorCategories && canReadEntity("product_categories") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
717
1136
|
href: "/admin/product_categories",
|
|
718
1137
|
className: `${linkCls} ${isActive("/admin/product_categories") ? linkActive : linkInactive}`
|
|
719
1138
|
}, /* @__PURE__ */ React.createElement(LucideIcons.FolderTree, {
|
|
720
1139
|
className: `h-4 w-4 mr-2 ${isActive("/admin/product_categories") ? iconActive : iconInactive}`
|
|
721
|
-
}), "Categories")), showVendorCollections && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1140
|
+
}), "Categories")), showVendorCollections && canReadEntity("collections") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
722
1141
|
href: "/admin/collections",
|
|
723
1142
|
className: `${linkCls} ${isActive("/admin/collections") ? linkActive : linkInactive}`
|
|
724
1143
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Layers, {
|
|
725
1144
|
className: `h-4 w-4 mr-2 ${isActive("/admin/collections") ? iconActive : iconInactive}`
|
|
726
|
-
}), "Collections")), showVendorBrands && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1145
|
+
}), "Collections")), showVendorBrands && canReadEntity("brands") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
727
1146
|
href: "/admin/brands",
|
|
728
1147
|
className: `${linkCls} ${isActive("/admin/brands") ? linkActive : linkInactive}`
|
|
729
1148
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Building2, {
|
|
730
1149
|
className: `h-4 w-4 mr-2 ${isActive("/admin/brands") ? iconActive : iconInactive}`
|
|
731
|
-
}), "Brands")), !hasCustomEventsNav && eventsEnabled !== false ? /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1150
|
+
}), "Brands")), !hasCustomEventsNav && eventsEnabled !== false && canReadEntity("events") ? /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
732
1151
|
href: "/admin/events",
|
|
733
1152
|
className: `${linkCls} ${isActive("/admin/events") ? linkActive : linkInactive}`
|
|
734
1153
|
}, /* @__PURE__ */ React.createElement(LucideIcons.CalendarDays, {
|
|
735
1154
|
className: `h-4 w-4 mr-2 ${isActive("/admin/events") ? iconActive : iconInactive}`
|
|
736
|
-
}), "Events")) : null, /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1155
|
+
}), "Events")) : null, canReadEntity("products") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
737
1156
|
href: "/admin/products",
|
|
738
1157
|
className: `${linkCls} ${isActive("/admin/products") ? linkActive : linkInactive}`
|
|
739
1158
|
}, /* @__PURE__ */ React.createElement(LucideIcons.ShoppingBag, {
|
|
740
1159
|
className: `h-4 w-4 mr-2 ${isActive("/admin/products") ? iconActive : iconInactive}`
|
|
741
|
-
}), "Products")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1160
|
+
}), "Products")), canReadEntity("combos") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
742
1161
|
href: "/admin/combos",
|
|
743
1162
|
className: `${linkCls} ${isActive("/admin/combos") ? linkActive : linkInactive}`
|
|
744
1163
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Package, {
|
|
745
1164
|
className: `h-4 w-4 mr-2 ${isActive("/admin/combos") ? iconActive : iconInactive}`
|
|
746
|
-
}), "Combos")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1165
|
+
}), "Combos")), canReadEntity("taxes") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
747
1166
|
href: "/admin/taxes",
|
|
748
1167
|
className: `${linkCls} ${isActive("/admin/taxes") ? linkActive : linkInactive}`
|
|
749
1168
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Receipt, {
|
|
750
1169
|
className: `h-4 w-4 mr-2 ${isActive("/admin/taxes") ? iconActive : iconInactive}`
|
|
751
|
-
}), "Taxes")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1170
|
+
}), "Taxes")), canReadEntity("discounts") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
752
1171
|
href: "/admin/discounts",
|
|
753
1172
|
className: `${linkCls} ${isActive("/admin/discounts") ? linkActive : linkInactive}`
|
|
754
1173
|
}, /* @__PURE__ */ React.createElement(LucideIcons.BadgePercent, {
|
|
755
1174
|
className: `h-4 w-4 mr-2 ${isActive("/admin/discounts") ? iconActive : iconInactive}`
|
|
756
|
-
}), "Discounts")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1175
|
+
}), "Discounts")), canReadEntity("orders") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
757
1176
|
href: "/admin/orders",
|
|
758
1177
|
className: `${linkCls} ${isActive("/admin/orders") ? linkActive : linkInactive}`
|
|
759
1178
|
}, /* @__PURE__ */ React.createElement(LucideIcons.ShoppingCart, {
|
|
760
1179
|
className: `h-4 w-4 mr-2 ${isActive("/admin/orders") ? iconActive : iconInactive}`
|
|
761
|
-
}), "Orders")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1180
|
+
}), "Orders")), canReadEntity("payments") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
762
1181
|
href: "/admin/payments",
|
|
763
1182
|
className: `${linkCls} ${isActive("/admin/payments") ? linkActive : linkInactive}`
|
|
764
1183
|
}, /* @__PURE__ */ React.createElement(LucideIcons.CreditCard, {
|
|
765
1184
|
className: `h-4 w-4 mr-2 ${isActive("/admin/payments") ? iconActive : iconInactive}`
|
|
766
|
-
}), "Payments")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1185
|
+
}), "Payments")), canReadEntity("vendor_customers") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
767
1186
|
href: "/admin/vendor_customers",
|
|
768
1187
|
className: `${linkCls} ${isActive("/admin/vendor_customers") ? linkActive : linkInactive}`
|
|
769
1188
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Users, {
|
|
@@ -774,32 +1193,32 @@ function AdminSidebar({ variant = "sidebar" }) {
|
|
|
774
1193
|
className: headingCls
|
|
775
1194
|
}, "Management"), /* @__PURE__ */ React.createElement("ul", {
|
|
776
1195
|
className: "space-y-0.5"
|
|
777
|
-
}, /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1196
|
+
}, canReadEntity("contacts") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
778
1197
|
href: "/admin/contacts",
|
|
779
1198
|
className: `${linkCls} ${isActive("/admin/contacts") ? linkActive : linkInactive}`
|
|
780
1199
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Inbox, {
|
|
781
1200
|
className: `h-4 w-4 mr-2 ${isActive("/admin/contacts") ? iconActive : iconInactive}`
|
|
782
|
-
}), "Contacts")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1201
|
+
}), "Contacts")), canReadEntity("blogs") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
783
1202
|
href: "/admin/blogs",
|
|
784
1203
|
className: `${linkCls} ${isActive("/admin/blogs") ? linkActive : linkInactive}`
|
|
785
1204
|
}, /* @__PURE__ */ React.createElement(LucideIcons.File, {
|
|
786
1205
|
className: `h-4 w-4 mr-2 ${isActive("/admin/blogs") ? iconActive : iconInactive}`
|
|
787
|
-
}), "Blogs")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1206
|
+
}), "Blogs")), canReadEntity("pages") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
788
1207
|
href: "/admin/pages",
|
|
789
1208
|
className: `${linkCls} ${isActive("/admin/pages") ? linkActive : linkInactive}`
|
|
790
1209
|
}, /* @__PURE__ */ React.createElement(LucideIcons.LinkIcon, {
|
|
791
1210
|
className: `h-4 w-4 mr-2 ${isActive("/admin/pages") ? iconActive : iconInactive}`
|
|
792
|
-
}), "Pages")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1211
|
+
}), "Pages")), canReadEntity("forms") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
793
1212
|
href: "/admin/forms",
|
|
794
1213
|
className: `${linkCls} ${isActive("/admin/forms") ? linkActive : linkInactive}`
|
|
795
1214
|
}, /* @__PURE__ */ React.createElement(LucideIcons.ClipboardList, {
|
|
796
1215
|
className: `h-4 w-4 mr-2 ${isActive("/admin/forms") ? iconActive : iconInactive}`
|
|
797
|
-
}), "Forms")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1216
|
+
}), "Forms")), canReadEntity("form_submissions") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
798
1217
|
href: "/admin/submissions",
|
|
799
1218
|
className: `${linkCls} ${isActive("/admin/submissions") ? linkActive : linkInactive}`
|
|
800
1219
|
}, /* @__PURE__ */ React.createElement(LucideIcons.MessageSquare, {
|
|
801
1220
|
className: `h-4 w-4 mr-2 ${isActive("/admin/submissions") ? iconActive : iconInactive}`
|
|
802
|
-
}), "Submissions")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1221
|
+
}), "Submissions")), canReadEntity("upload") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
803
1222
|
href: "/admin/media",
|
|
804
1223
|
className: `${linkCls} ${isActive("/admin/media") ? linkActive : linkInactive}`
|
|
805
1224
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Image, {
|
|
@@ -836,12 +1255,12 @@ function AdminSidebar({ variant = "sidebar" }) {
|
|
|
836
1255
|
className: headingCls
|
|
837
1256
|
}, "System"), /* @__PURE__ */ React.createElement("ul", {
|
|
838
1257
|
className: "space-y-0.5"
|
|
839
|
-
}, /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1258
|
+
}, canReadEntity("users") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
840
1259
|
href: "/admin/users",
|
|
841
1260
|
className: `${linkCls} ${isActive("/admin/users") ? linkActive : linkInactive}`
|
|
842
1261
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Users, {
|
|
843
1262
|
className: `h-4 w-4 mr-2 ${isActive("/admin/users") ? iconActive : iconInactive}`
|
|
844
|
-
}), "Users")), /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
1263
|
+
}), "Users")), canReadEntity("roles") && /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
845
1264
|
href: "/admin/roles",
|
|
846
1265
|
className: `${linkCls} ${isActive("/admin/roles") ? linkActive : linkInactive}`
|
|
847
1266
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Shield, {
|
|
@@ -888,6 +1307,7 @@ var init_Sidebar = __esm({
|
|
|
888
1307
|
"src/components/Admin/Sidebar.tsx"() {
|
|
889
1308
|
"use client";
|
|
890
1309
|
init_vendor_scope();
|
|
1310
|
+
init_rbac_debug();
|
|
891
1311
|
init_admin_config_context();
|
|
892
1312
|
init_infuro_favicon();
|
|
893
1313
|
init_cms_version();
|
|
@@ -1514,7 +1934,15 @@ function useEventsSettings() {
|
|
|
1514
1934
|
requireEventApproval
|
|
1515
1935
|
};
|
|
1516
1936
|
}
|
|
1517
|
-
function AdminLayout({ children, customNavItems = [], customNavSections = [], customCrudConfigs = {}, categoryRelatedProductLabels = {}, renderOrderDetailFooter, theme, themeRegistry, pluginDescriptors = [] }) {
|
|
1937
|
+
function AdminLayout({ children, customNavItems = [], customNavSections = [], customCrudConfigs = {}, categoryRelatedProductLabels = {}, renderOrderDetailFooter, extraNotificationVariables, theme, themeRegistry, pluginDescriptors = [] }) {
|
|
1938
|
+
React25.useEffect(() => {
|
|
1939
|
+
document.documentElement.style.overflow = "hidden";
|
|
1940
|
+
document.body.style.overflow = "hidden";
|
|
1941
|
+
return () => {
|
|
1942
|
+
document.documentElement.style.overflow = "";
|
|
1943
|
+
document.body.style.overflow = "";
|
|
1944
|
+
};
|
|
1945
|
+
}, []);
|
|
1518
1946
|
const resolvedTheme = useResolvedTheme(theme, themeRegistry);
|
|
1519
1947
|
const { storeEnabled, currency } = useStoreEnabled();
|
|
1520
1948
|
const { multiVendorEnabled, vendorCanCreateCategories, vendorCanCreateCollections, vendorCanCreateBrands, requireProductApproval } = useMultiVendorSettings();
|
|
@@ -1535,6 +1963,7 @@ function AdminLayout({ children, customNavItems = [], customNavSections = [], cu
|
|
|
1535
1963
|
customCrudConfigs,
|
|
1536
1964
|
categoryRelatedProductLabels,
|
|
1537
1965
|
renderOrderDetailFooter,
|
|
1966
|
+
extraNotificationVariables,
|
|
1538
1967
|
theme: resolvedTheme,
|
|
1539
1968
|
themeRegistry,
|
|
1540
1969
|
pluginDescriptors: mergedPluginDescriptors,
|
|
@@ -1553,6 +1982,7 @@ function AdminLayout({ children, customNavItems = [], customNavSections = [], cu
|
|
|
1553
1982
|
customCrudConfigs,
|
|
1554
1983
|
categoryRelatedProductLabels,
|
|
1555
1984
|
renderOrderDetailFooter,
|
|
1985
|
+
extraNotificationVariables,
|
|
1556
1986
|
resolvedTheme,
|
|
1557
1987
|
themeRegistry,
|
|
1558
1988
|
mergedPluginDescriptors,
|
|
@@ -4409,6 +4839,8 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
4409
4839
|
const hasLoadedRef = React25.useRef(false);
|
|
4410
4840
|
const isMobile = useIsMobile();
|
|
4411
4841
|
const showGroupColumn = !!manageUserGroups && roleOptions.length > 0;
|
|
4842
|
+
const { data: session } = react.useSession();
|
|
4843
|
+
const sessionUser = session?.user;
|
|
4412
4844
|
const listColumns = React25.useMemo(() => Array.isArray(columns) ? columns.filter((c) => !c.hideInTable) : [], [
|
|
4413
4845
|
columns
|
|
4414
4846
|
]);
|
|
@@ -4949,6 +5381,9 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
4949
5381
|
withListFrom
|
|
4950
5382
|
]);
|
|
4951
5383
|
const resourceName = apiEndpoint.replace("/api/", "");
|
|
5384
|
+
const canCreate = !sessionUser || sessionHasEntityAccessFromExplanation(sessionUser, resourceName, "create");
|
|
5385
|
+
const canUpdate = !sessionUser || sessionHasEntityAccessFromExplanation(sessionUser, resourceName, "update");
|
|
5386
|
+
const canDelete = !sessionUser || sessionHasEntityAccessFromExplanation(sessionUser, resourceName, "delete");
|
|
4952
5387
|
const dedicatedRecordEditHref = /* @__PURE__ */ __name((recordId) => addEditPage && (resourceName === "orders" || resourceName === "events") ? withListFrom(`${addEditPageUrl}/${recordId}/edit`) : addEditPage ? withListFrom(`${addEditPageUrl}/${recordId}`) : "", "dedicatedRecordEditHref");
|
|
4953
5388
|
const showDedicatedDuplicate = addEditPage && !CRUD_NO_DUPLICATE_RESOURCES.has(resourceName);
|
|
4954
5389
|
const hasCustomView = customViewPageUrl && customViewPageUrl.length > 0;
|
|
@@ -5108,15 +5543,15 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5108
5543
|
onClick: /* @__PURE__ */ __name(() => setBulkDialogOpen(true), "onClick"),
|
|
5109
5544
|
variant: "outline",
|
|
5110
5545
|
className: "bg-transparent text-white border-gray-600 hover:bg-gray-700 text-xs h-8"
|
|
5111
|
-
}, /* @__PURE__ */ React.createElement(LucideIcons.
|
|
5546
|
+
}, /* @__PURE__ */ React.createElement(LucideIcons.Download, {
|
|
5112
5547
|
className: "h-3.5 w-3.5 mr-1"
|
|
5113
5548
|
}), "Import"), /* @__PURE__ */ React.createElement(Button, {
|
|
5114
5549
|
onClick: handleExport,
|
|
5115
5550
|
variant: "outline",
|
|
5116
5551
|
className: "bg-transparent text-white border-gray-600 hover:bg-gray-700 text-xs h-8"
|
|
5117
|
-
}, /* @__PURE__ */ React.createElement(LucideIcons.
|
|
5552
|
+
}, /* @__PURE__ */ React.createElement(LucideIcons.Upload, {
|
|
5118
5553
|
className: "h-3.5 w-3.5 mr-1"
|
|
5119
|
-
}), "Export"), !addEditPage && /* @__PURE__ */ React.createElement(Button, {
|
|
5554
|
+
}), "Export"), canCreate && !addEditPage && /* @__PURE__ */ React.createElement(Button, {
|
|
5120
5555
|
onClick: /* @__PURE__ */ __name(() => {
|
|
5121
5556
|
setEditingItem(null);
|
|
5122
5557
|
setDuplicateSeed(null);
|
|
@@ -5125,7 +5560,7 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5125
5560
|
className: "bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs h-8"
|
|
5126
5561
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Plus, {
|
|
5127
5562
|
className: "h-3.5 w-3.5"
|
|
5128
|
-
}), "Add"), addEditPage && dedicatedCreateHref && /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
5563
|
+
}), "Add"), canCreate && addEditPage && dedicatedCreateHref && /* @__PURE__ */ React.createElement(Link2__default.default, {
|
|
5129
5564
|
href: dedicatedCreateHref,
|
|
5130
5565
|
className: "inline-flex items-center gap-1 bg-white text-gray-800 hover:bg-gray-100 border-0 text-xs h-8 px-3 rounded-md font-medium"
|
|
5131
5566
|
}, /* @__PURE__ */ React.createElement(LucideIcons.Plus, {
|
|
@@ -5284,7 +5719,7 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5284
5719
|
onClick: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onClick")
|
|
5285
5720
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
5286
5721
|
className: "flex items-center justify-center gap-1"
|
|
5287
|
-
}, customRowActions ? customRowActions(item) : /* @__PURE__ */ React.createElement(React.Fragment, null, !addEditPage && /* @__PURE__ */ React.createElement(Button, {
|
|
5722
|
+
}, customRowActions ? customRowActions(item) : /* @__PURE__ */ React.createElement(React.Fragment, null, canUpdate && !addEditPage && /* @__PURE__ */ React.createElement(Button, {
|
|
5288
5723
|
variant: "outline",
|
|
5289
5724
|
size: "icon",
|
|
5290
5725
|
className: "h-7 w-7",
|
|
@@ -5294,7 +5729,7 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5294
5729
|
className: "h-3.5 w-3.5"
|
|
5295
5730
|
}), /* @__PURE__ */ React.createElement("span", {
|
|
5296
5731
|
className: "sr-only"
|
|
5297
|
-
}, "Edit")), addEditPage && /* @__PURE__ */ React.createElement(Button, {
|
|
5732
|
+
}, "Edit")), canUpdate && addEditPage && /* @__PURE__ */ React.createElement(Button, {
|
|
5298
5733
|
variant: "outline",
|
|
5299
5734
|
size: "icon",
|
|
5300
5735
|
className: "h-7 w-7",
|
|
@@ -5304,7 +5739,7 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5304
5739
|
className: "h-3.5 w-3.5"
|
|
5305
5740
|
}), /* @__PURE__ */ React.createElement("span", {
|
|
5306
5741
|
className: "sr-only"
|
|
5307
|
-
}, "Edit")), showDuplicateEntry && /* @__PURE__ */ React.createElement(Button, {
|
|
5742
|
+
}, "Edit")), canCreate && showDuplicateEntry && /* @__PURE__ */ React.createElement(Button, {
|
|
5308
5743
|
variant: "outline",
|
|
5309
5744
|
size: "icon",
|
|
5310
5745
|
className: "h-7 w-7",
|
|
@@ -5330,7 +5765,7 @@ function AdminCRUD({ title, apiEndpoint, columns, addEditPageUrl, customViewPage
|
|
|
5330
5765
|
className: "h-3.5 w-3.5"
|
|
5331
5766
|
}), /* @__PURE__ */ React.createElement("span", {
|
|
5332
5767
|
className: "sr-only"
|
|
5333
|
-
}, "Resend invite")), /* @__PURE__ */ React.createElement(Button, {
|
|
5768
|
+
}, "Resend invite")), canDelete && /* @__PURE__ */ React.createElement(Button, {
|
|
5334
5769
|
variant: "outline",
|
|
5335
5770
|
size: "icon",
|
|
5336
5771
|
className: "h-7 w-7 border-red-300 text-red-600 hover:text-red-700",
|
|
@@ -5468,6 +5903,7 @@ var init_CRUD = __esm({
|
|
|
5468
5903
|
init_dropdown_menu();
|
|
5469
5904
|
init_utils();
|
|
5470
5905
|
init_use_mobile();
|
|
5906
|
+
init_rbac_debug();
|
|
5471
5907
|
init_BulkUploadDialog();
|
|
5472
5908
|
init_admin_list_return_url();
|
|
5473
5909
|
init_build_crud_list_filters_from_columns();
|
|
@@ -15536,6 +15972,18 @@ var init_email_recipients = __esm({
|
|
|
15536
15972
|
__name(serializeEmailRecipients, "serializeEmailRecipients");
|
|
15537
15973
|
}
|
|
15538
15974
|
});
|
|
15975
|
+
function useNotificationVariables() {
|
|
15976
|
+
const config = React25.useContext(exports.AdminConfigContext);
|
|
15977
|
+
const extra = config?.extraNotificationVariables ?? [];
|
|
15978
|
+
const vars = [
|
|
15979
|
+
...KNOWN_VARS,
|
|
15980
|
+
...extra.map((e) => e.name)
|
|
15981
|
+
];
|
|
15982
|
+
return {
|
|
15983
|
+
vars,
|
|
15984
|
+
extra
|
|
15985
|
+
};
|
|
15986
|
+
}
|
|
15539
15987
|
function getEmailTriggerDefaults(triggerKey, audience = "customer") {
|
|
15540
15988
|
if (audience === "vendor") {
|
|
15541
15989
|
return VENDOR_EMAIL_TRIGGER_DEFAULTS[triggerKey] ?? {
|
|
@@ -15679,6 +16127,7 @@ var KNOWN_VARS, EMAIL_TRIGGER_DEFAULTS, VENDOR_EMAIL_TRIGGER_DEFAULTS, ADMIN_EMA
|
|
|
15679
16127
|
var init_order_notification_bindings_shared = __esm({
|
|
15680
16128
|
"src/admin/components/order-notification-bindings-shared.ts"() {
|
|
15681
16129
|
"use client";
|
|
16130
|
+
init_admin_config_context();
|
|
15682
16131
|
KNOWN_VARS = [
|
|
15683
16132
|
"orderId",
|
|
15684
16133
|
"orderNumber",
|
|
@@ -15693,6 +16142,7 @@ var init_order_notification_bindings_shared = __esm({
|
|
|
15693
16142
|
"invoiceNumber",
|
|
15694
16143
|
"invoiceUrl"
|
|
15695
16144
|
];
|
|
16145
|
+
__name(useNotificationVariables, "useNotificationVariables");
|
|
15696
16146
|
EMAIL_TRIGGER_DEFAULTS = {
|
|
15697
16147
|
order_placed: {
|
|
15698
16148
|
subject: "Your order {{orderNumber}} is confirmed",
|
|
@@ -16396,16 +16846,23 @@ function TriggerEmailEditor({ triggerKey, label, description, audience = "custom
|
|
|
16396
16846
|
cancelled = true;
|
|
16397
16847
|
};
|
|
16398
16848
|
}, []);
|
|
16849
|
+
const { vars: availableVars, extra: extraVars } = useNotificationVariables();
|
|
16399
16850
|
const visibleVars = React25.useMemo(() => {
|
|
16400
|
-
return
|
|
16851
|
+
return availableVars.filter((v) => {
|
|
16401
16852
|
if (v === "vendorName" || v === "vendorId") return multiVendorOn;
|
|
16402
16853
|
if (v === "eventName") return eventsOn;
|
|
16403
16854
|
return true;
|
|
16404
16855
|
});
|
|
16405
16856
|
}, [
|
|
16857
|
+
availableVars,
|
|
16406
16858
|
multiVendorOn,
|
|
16407
16859
|
eventsOn
|
|
16408
16860
|
]);
|
|
16861
|
+
const getVarHint = /* @__PURE__ */ __name((v) => {
|
|
16862
|
+
if (v in VAR_HINTS) return VAR_HINTS[v];
|
|
16863
|
+
const match = extraVars.find((e) => e.name === v);
|
|
16864
|
+
return match?.hint || match?.label || v;
|
|
16865
|
+
}, "getVarHint");
|
|
16409
16866
|
return /* @__PURE__ */ React.createElement("div", {
|
|
16410
16867
|
className: "space-y-3 border-t border-gray-100 pt-4 first:border-t-0 first:pt-0 dark:border-gray-700"
|
|
16411
16868
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
@@ -16468,7 +16925,7 @@ function TriggerEmailEditor({ triggerKey, label, description, audience = "custom
|
|
|
16468
16925
|
}, visibleVars.map((v) => /* @__PURE__ */ React.createElement("button", {
|
|
16469
16926
|
key: v,
|
|
16470
16927
|
type: "button",
|
|
16471
|
-
title:
|
|
16928
|
+
title: getVarHint(v),
|
|
16472
16929
|
onClick: /* @__PURE__ */ __name(() => insertVariable(v), "onClick"),
|
|
16473
16930
|
className: "rounded border border-gray-200 bg-white px-2 py-1 font-mono text-[11px] text-gray-700 hover:border-blue-300 hover:bg-blue-50 dark:border-gray-600 dark:bg-gray-900 dark:text-gray-300 dark:hover:border-blue-700 dark:hover:bg-blue-950/40"
|
|
16474
16931
|
}, `{{${v}}}`))), /* @__PURE__ */ React.createElement("p", {
|
|
@@ -16514,6 +16971,12 @@ function PushTriggerBindings({ audience = "customer" }) {
|
|
|
16514
16971
|
const bodyRef = React25.useRef(null);
|
|
16515
16972
|
const subjectRef = React25.useRef(null);
|
|
16516
16973
|
const lastFocused = React25.useRef("body");
|
|
16974
|
+
const { vars: availableVars, extra: extraVars } = useNotificationVariables();
|
|
16975
|
+
const getVarHint = /* @__PURE__ */ __name((v) => {
|
|
16976
|
+
if (v in VAR_HINTS2) return VAR_HINTS2[v];
|
|
16977
|
+
const match = extraVars.find((e) => e.name === v);
|
|
16978
|
+
return match?.hint || match?.label || v;
|
|
16979
|
+
}, "getVarHint");
|
|
16517
16980
|
React25.useEffect(() => {
|
|
16518
16981
|
let cancelled = false;
|
|
16519
16982
|
(async () => {
|
|
@@ -16735,11 +17198,11 @@ function PushTriggerBindings({ audience = "customer" }) {
|
|
|
16735
17198
|
className: "text-xs font-medium text-gray-700 dark:text-gray-300"
|
|
16736
17199
|
}, "Insert Variables"), /* @__PURE__ */ React.createElement("div", {
|
|
16737
17200
|
className: "flex flex-wrap gap-1.5"
|
|
16738
|
-
},
|
|
17201
|
+
}, availableVars.map((v) => /* @__PURE__ */ React.createElement("button", {
|
|
16739
17202
|
key: v,
|
|
16740
17203
|
type: "button",
|
|
16741
17204
|
onClick: /* @__PURE__ */ __name(() => insertVariable(v), "onClick"),
|
|
16742
|
-
title:
|
|
17205
|
+
title: getVarHint(v),
|
|
16743
17206
|
className: "px-2 py-1 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 rounded text-xs font-mono border border-gray-200 dark:border-gray-700 transition-colors"
|
|
16744
17207
|
}, `{{${v}}}`)))), /* @__PURE__ */ React.createElement("div", {
|
|
16745
17208
|
className: "space-y-1.5"
|
|
@@ -20845,183 +21308,6 @@ var init_PluginsPage = __esm({
|
|
|
20845
21308
|
}
|
|
20846
21309
|
});
|
|
20847
21310
|
|
|
20848
|
-
// src/lib/vendor-role-defaults.ts
|
|
20849
|
-
function full() {
|
|
20850
|
-
return {
|
|
20851
|
-
canCreate: true,
|
|
20852
|
-
canRead: true,
|
|
20853
|
-
canUpdate: true,
|
|
20854
|
-
canDelete: true
|
|
20855
|
-
};
|
|
20856
|
-
}
|
|
20857
|
-
function read() {
|
|
20858
|
-
return {
|
|
20859
|
-
canCreate: false,
|
|
20860
|
-
canRead: true,
|
|
20861
|
-
canUpdate: false,
|
|
20862
|
-
canDelete: false
|
|
20863
|
-
};
|
|
20864
|
-
}
|
|
20865
|
-
function none() {
|
|
20866
|
-
return {
|
|
20867
|
-
canCreate: false,
|
|
20868
|
-
canRead: false,
|
|
20869
|
-
canUpdate: false,
|
|
20870
|
-
canDelete: false
|
|
20871
|
-
};
|
|
20872
|
-
}
|
|
20873
|
-
function readUpdate() {
|
|
20874
|
-
return {
|
|
20875
|
-
canCreate: false,
|
|
20876
|
-
canRead: true,
|
|
20877
|
-
canUpdate: true,
|
|
20878
|
-
canDelete: false
|
|
20879
|
-
};
|
|
20880
|
-
}
|
|
20881
|
-
function storePerms(spec) {
|
|
20882
|
-
const resolve = /* @__PURE__ */ __name((v) => {
|
|
20883
|
-
if (v === "full") return full();
|
|
20884
|
-
if (v === "read") return read();
|
|
20885
|
-
if (v === "none") return none();
|
|
20886
|
-
return v;
|
|
20887
|
-
}, "resolve");
|
|
20888
|
-
const out = {};
|
|
20889
|
-
for (const entity of STORE_ENTITIES) {
|
|
20890
|
-
out[entity] = resolve(spec[entity] ?? "none");
|
|
20891
|
-
}
|
|
20892
|
-
return out;
|
|
20893
|
-
}
|
|
20894
|
-
var STORE_ENTITIES;
|
|
20895
|
-
var init_vendor_role_defaults = __esm({
|
|
20896
|
-
"src/lib/vendor-role-defaults.ts"() {
|
|
20897
|
-
init_vendor_scope();
|
|
20898
|
-
[
|
|
20899
|
-
...VENDOR_STORE_RBAC_ENTITIES,
|
|
20900
|
-
"dashboard",
|
|
20901
|
-
"settings",
|
|
20902
|
-
"team",
|
|
20903
|
-
"roles"
|
|
20904
|
-
];
|
|
20905
|
-
STORE_ENTITIES = [
|
|
20906
|
-
...VENDOR_STORE_RBAC_ENTITIES
|
|
20907
|
-
];
|
|
20908
|
-
__name(full, "full");
|
|
20909
|
-
__name(read, "read");
|
|
20910
|
-
__name(none, "none");
|
|
20911
|
-
__name(readUpdate, "readUpdate");
|
|
20912
|
-
__name(storePerms, "storePerms");
|
|
20913
|
-
[
|
|
20914
|
-
{
|
|
20915
|
-
name: "Owner",
|
|
20916
|
-
description: "Full store access and team/role management",
|
|
20917
|
-
isSystem: true,
|
|
20918
|
-
isOwnerRole: true,
|
|
20919
|
-
permissions: {
|
|
20920
|
-
...storePerms(Object.fromEntries(STORE_ENTITIES.map((e) => [
|
|
20921
|
-
e,
|
|
20922
|
-
"full"
|
|
20923
|
-
]))),
|
|
20924
|
-
dashboard: read(),
|
|
20925
|
-
settings: readUpdate(),
|
|
20926
|
-
team: full(),
|
|
20927
|
-
roles: full()
|
|
20928
|
-
}
|
|
20929
|
-
},
|
|
20930
|
-
{
|
|
20931
|
-
name: "Manager",
|
|
20932
|
-
description: "Day-to-day store operations",
|
|
20933
|
-
isSystem: true,
|
|
20934
|
-
isOwnerRole: false,
|
|
20935
|
-
permissions: {
|
|
20936
|
-
...storePerms({
|
|
20937
|
-
products: "full",
|
|
20938
|
-
collections: "full",
|
|
20939
|
-
brands: "full",
|
|
20940
|
-
product_categories: "full",
|
|
20941
|
-
orders: "full",
|
|
20942
|
-
vendor_customers: "full",
|
|
20943
|
-
discounts: "full",
|
|
20944
|
-
order_discounts: "full",
|
|
20945
|
-
order_addresses: "full",
|
|
20946
|
-
payments: "read",
|
|
20947
|
-
taxes: "read",
|
|
20948
|
-
attributes: "read"
|
|
20949
|
-
}),
|
|
20950
|
-
dashboard: read(),
|
|
20951
|
-
settings: read(),
|
|
20952
|
-
team: none(),
|
|
20953
|
-
roles: none()
|
|
20954
|
-
}
|
|
20955
|
-
},
|
|
20956
|
-
{
|
|
20957
|
-
name: "Catalog Staff",
|
|
20958
|
-
description: "Manage products and catalog content",
|
|
20959
|
-
isSystem: true,
|
|
20960
|
-
isOwnerRole: false,
|
|
20961
|
-
permissions: {
|
|
20962
|
-
...storePerms({
|
|
20963
|
-
products: "full",
|
|
20964
|
-
collections: "full",
|
|
20965
|
-
brands: "full",
|
|
20966
|
-
product_categories: "full",
|
|
20967
|
-
attributes: "full",
|
|
20968
|
-
orders: "read",
|
|
20969
|
-
vendor_customers: "read"
|
|
20970
|
-
}),
|
|
20971
|
-
dashboard: read(),
|
|
20972
|
-
settings: none(),
|
|
20973
|
-
team: none(),
|
|
20974
|
-
roles: none()
|
|
20975
|
-
}
|
|
20976
|
-
},
|
|
20977
|
-
{
|
|
20978
|
-
name: "Fulfillment",
|
|
20979
|
-
description: "Orders and fulfillment",
|
|
20980
|
-
isSystem: true,
|
|
20981
|
-
isOwnerRole: false,
|
|
20982
|
-
permissions: {
|
|
20983
|
-
...storePerms({
|
|
20984
|
-
products: "read",
|
|
20985
|
-
orders: "full",
|
|
20986
|
-
order_addresses: "full",
|
|
20987
|
-
order_discounts: "read",
|
|
20988
|
-
vendor_customers: "read"
|
|
20989
|
-
}),
|
|
20990
|
-
dashboard: read(),
|
|
20991
|
-
settings: none(),
|
|
20992
|
-
team: none(),
|
|
20993
|
-
roles: none()
|
|
20994
|
-
}
|
|
20995
|
-
},
|
|
20996
|
-
{
|
|
20997
|
-
name: "Viewer",
|
|
20998
|
-
description: "Read-only access to store data",
|
|
20999
|
-
isSystem: true,
|
|
21000
|
-
isOwnerRole: false,
|
|
21001
|
-
permissions: {
|
|
21002
|
-
...storePerms(Object.fromEntries(STORE_ENTITIES.map((e) => [
|
|
21003
|
-
e,
|
|
21004
|
-
"read"
|
|
21005
|
-
]))),
|
|
21006
|
-
dashboard: read(),
|
|
21007
|
-
settings: none(),
|
|
21008
|
-
team: none(),
|
|
21009
|
-
roles: none()
|
|
21010
|
-
}
|
|
21011
|
-
}
|
|
21012
|
-
];
|
|
21013
|
-
}
|
|
21014
|
-
});
|
|
21015
|
-
|
|
21016
|
-
// src/auth/rbac-debug.ts
|
|
21017
|
-
var init_rbac_debug = __esm({
|
|
21018
|
-
"src/auth/rbac-debug.ts"() {
|
|
21019
|
-
init_permission_entities();
|
|
21020
|
-
init_vendor_role_defaults();
|
|
21021
|
-
init_vendor_scope();
|
|
21022
|
-
}
|
|
21023
|
-
});
|
|
21024
|
-
|
|
21025
21311
|
// src/auth/helpers.ts
|
|
21026
21312
|
function canManageRoles(user) {
|
|
21027
21313
|
return !!(user?.email && user.isRBACAdmin);
|
|
@@ -21179,23 +21465,6 @@ function VendorRolesPage() {
|
|
|
21179
21465
|
return next;
|
|
21180
21466
|
});
|
|
21181
21467
|
}, "setAllRows");
|
|
21182
|
-
const toggleEntityRow = /* @__PURE__ */ __name((entity) => {
|
|
21183
|
-
const isOwnerOnlyEntity = entity === "team" || entity === "roles";
|
|
21184
|
-
setMatrix((prev) => {
|
|
21185
|
-
const current = prev[entity];
|
|
21186
|
-
const isAllChecked = current?.canRead && (isOwnerOnlyEntity || current.canCreate && current.canUpdate && current.canDelete);
|
|
21187
|
-
return {
|
|
21188
|
-
...prev,
|
|
21189
|
-
[entity]: {
|
|
21190
|
-
entity,
|
|
21191
|
-
canRead: !isAllChecked,
|
|
21192
|
-
canCreate: isOwnerOnlyEntity ? false : !isAllChecked,
|
|
21193
|
-
canUpdate: isOwnerOnlyEntity ? false : !isAllChecked,
|
|
21194
|
-
canDelete: isOwnerOnlyEntity ? false : !isAllChecked
|
|
21195
|
-
}
|
|
21196
|
-
};
|
|
21197
|
-
});
|
|
21198
|
-
}, "toggleEntityRow");
|
|
21199
21468
|
const saveMatrix = /* @__PURE__ */ __name(async () => {
|
|
21200
21469
|
if (!selectedId) return;
|
|
21201
21470
|
setSaving(true);
|
|
@@ -21389,31 +21658,35 @@ function VendorRolesPage() {
|
|
|
21389
21658
|
}), " Clear All"))), /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
21390
21659
|
className: "overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-700"
|
|
21391
21660
|
}, /* @__PURE__ */ React25__namespace.default.createElement("table", {
|
|
21392
|
-
className: "min-w-full text-
|
|
21661
|
+
className: "min-w-full text-sm"
|
|
21393
21662
|
}, /* @__PURE__ */ React25__namespace.default.createElement("thead", {
|
|
21394
|
-
className: "bg-
|
|
21395
|
-
}, /* @__PURE__ */ React25__namespace.default.createElement("tr",
|
|
21396
|
-
className: "
|
|
21397
|
-
},
|
|
21398
|
-
className: "px-3 py-2 font-
|
|
21663
|
+
className: "bg-white dark:bg-gray-800"
|
|
21664
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("tr", {
|
|
21665
|
+
className: "border-b border-gray-200 dark:border-gray-700"
|
|
21666
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("th", {
|
|
21667
|
+
className: "px-3 py-2.5 text-left font-semibold text-gray-700 dark:text-gray-300"
|
|
21668
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
21669
|
+
className: "flex items-center gap-2"
|
|
21670
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("span", null, "Entity"))), /* @__PURE__ */ React25__namespace.default.createElement("th", {
|
|
21671
|
+
className: "px-3 py-2.5 text-center font-semibold text-gray-700 dark:text-gray-300"
|
|
21399
21672
|
}, "Create"), /* @__PURE__ */ React25__namespace.default.createElement("th", {
|
|
21400
|
-
className: "px-3 py-2 font-
|
|
21673
|
+
className: "px-3 py-2.5 text-center font-semibold text-gray-700 dark:text-gray-300"
|
|
21401
21674
|
}, "Read"), /* @__PURE__ */ React25__namespace.default.createElement("th", {
|
|
21402
|
-
className: "px-3 py-2 font-
|
|
21675
|
+
className: "px-3 py-2.5 text-center font-semibold text-gray-700 dark:text-gray-300"
|
|
21403
21676
|
}, "Update"), /* @__PURE__ */ React25__namespace.default.createElement("th", {
|
|
21404
|
-
className: "px-3 py-2 font-
|
|
21405
|
-
}, "Delete"), /* @__PURE__ */ React25__namespace.default.createElement("
|
|
21406
|
-
className: "px-3 py-2 font-medium text-right"
|
|
21407
|
-
}, "Row Actions"))), /* @__PURE__ */ React25__namespace.default.createElement("tbody", null, entities.map((entity) => {
|
|
21677
|
+
className: "px-3 py-2.5 text-center font-semibold text-gray-700 dark:text-gray-300"
|
|
21678
|
+
}, "Delete"))), /* @__PURE__ */ React25__namespace.default.createElement("tbody", null, entities.map((entity) => {
|
|
21408
21679
|
const isOwnerOnlyEntity = entity === "team" || entity === "roles";
|
|
21409
21680
|
return /* @__PURE__ */ React25__namespace.default.createElement("tr", {
|
|
21410
21681
|
key: entity,
|
|
21411
|
-
className: "border-
|
|
21682
|
+
className: "border-b border-gray-100 last:border-b-0 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800/50"
|
|
21412
21683
|
}, /* @__PURE__ */ React25__namespace.default.createElement("td", {
|
|
21413
|
-
className: "px-3 py-2 font-mono text-gray-800 dark:text-gray-200
|
|
21414
|
-
},
|
|
21415
|
-
className: "
|
|
21416
|
-
}, "
|
|
21684
|
+
className: "px-3 py-2.5 font-mono text-sm text-gray-800 dark:text-gray-200"
|
|
21685
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
21686
|
+
className: "flex items-center gap-2"
|
|
21687
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("span", null, entity), isOwnerOnlyEntity && /* @__PURE__ */ React25__namespace.default.createElement("span", {
|
|
21688
|
+
className: "text-[10px] text-amber-600 dark:text-amber-400"
|
|
21689
|
+
}, "(Owner managed)"))), [
|
|
21417
21690
|
"canCreate",
|
|
21418
21691
|
"canRead",
|
|
21419
21692
|
"canUpdate",
|
|
@@ -21422,21 +21695,15 @@ function VendorRolesPage() {
|
|
|
21422
21695
|
const disabled = isOwnerOnlyEntity && key !== "canRead";
|
|
21423
21696
|
return /* @__PURE__ */ React25__namespace.default.createElement("td", {
|
|
21424
21697
|
key,
|
|
21425
|
-
className: "px-3 py-2"
|
|
21698
|
+
className: "px-3 py-2.5 text-center"
|
|
21426
21699
|
}, /* @__PURE__ */ React25__namespace.default.createElement("input", {
|
|
21427
21700
|
type: "checkbox",
|
|
21428
21701
|
checked: disabled ? false : !!matrix[entity]?.[key],
|
|
21429
21702
|
disabled,
|
|
21430
21703
|
onChange: /* @__PURE__ */ __name(() => toggle(entity, key), "onChange"),
|
|
21431
|
-
className: disabled ? "cursor-not-allowed opacity-40" : "cursor-pointer"
|
|
21704
|
+
className: disabled ? "h-4 w-4 cursor-not-allowed opacity-40" : "h-4 w-4 cursor-pointer"
|
|
21432
21705
|
}));
|
|
21433
|
-
})
|
|
21434
|
-
className: "px-3 py-2 text-right"
|
|
21435
|
-
}, /* @__PURE__ */ React25__namespace.default.createElement("button", {
|
|
21436
|
-
type: "button",
|
|
21437
|
-
onClick: /* @__PURE__ */ __name(() => toggleEntityRow(entity), "onClick"),
|
|
21438
|
-
className: "text-[11px] text-blue-600 hover:underline dark:text-blue-400"
|
|
21439
|
-
}, "Toggle")));
|
|
21706
|
+
}));
|
|
21440
21707
|
})))))))), /* @__PURE__ */ React25__namespace.default.createElement(Dialog, {
|
|
21441
21708
|
open: deleteOpen,
|
|
21442
21709
|
onOpenChange: setDeleteOpen
|
|
@@ -22314,39 +22581,90 @@ var init_VendorTeamPage = __esm({
|
|
|
22314
22581
|
__name(VendorTeamPage, "VendorTeamPage");
|
|
22315
22582
|
}
|
|
22316
22583
|
});
|
|
22317
|
-
|
|
22318
|
-
|
|
22319
|
-
|
|
22320
|
-
|
|
22321
|
-
|
|
22584
|
+
function splitPhoneAndCountryCode(rawPhone, defaultCode = "+91") {
|
|
22585
|
+
if (!rawPhone || !rawPhone.trim()) {
|
|
22586
|
+
return {
|
|
22587
|
+
countryCode: defaultCode,
|
|
22588
|
+
phoneNumber: ""
|
|
22589
|
+
};
|
|
22322
22590
|
}
|
|
22323
|
-
|
|
22591
|
+
const trimmed = rawPhone.trim();
|
|
22592
|
+
const match = COUNTRY_PHONE_CODES.find((c) => trimmed.startsWith(c.code));
|
|
22593
|
+
if (match) {
|
|
22594
|
+
return {
|
|
22595
|
+
countryCode: match.code,
|
|
22596
|
+
phoneNumber: trimmed.slice(match.code.length).replace(/\s+/g, "")
|
|
22597
|
+
};
|
|
22598
|
+
}
|
|
22599
|
+
if (trimmed.startsWith("+")) {
|
|
22600
|
+
const spaceIdx = trimmed.indexOf(" ");
|
|
22601
|
+
if (spaceIdx > 0) {
|
|
22602
|
+
return {
|
|
22603
|
+
countryCode: trimmed.slice(0, spaceIdx),
|
|
22604
|
+
phoneNumber: trimmed.slice(spaceIdx + 1).replace(/\s+/g, "")
|
|
22605
|
+
};
|
|
22606
|
+
}
|
|
22607
|
+
}
|
|
22608
|
+
return {
|
|
22609
|
+
countryCode: defaultCode,
|
|
22610
|
+
phoneNumber: trimmed.replace(/\D/g, "")
|
|
22611
|
+
};
|
|
22612
|
+
}
|
|
22613
|
+
function formatPhoneWithCountryCode(countryCode, phoneNumber) {
|
|
22614
|
+
const cleanNum = phoneNumber.replace(/\D/g, "");
|
|
22615
|
+
if (!cleanNum) return null;
|
|
22616
|
+
const cleanCode = countryCode.trim() || "+91";
|
|
22617
|
+
return `${cleanCode}${cleanNum}`;
|
|
22618
|
+
}
|
|
22619
|
+
function validateGstin(gstin, options) {
|
|
22620
|
+
const required = options?.required === true;
|
|
22621
|
+
if (!gstin || !gstin.trim()) {
|
|
22622
|
+
if (required) return "GSTIN number is required";
|
|
22623
|
+
return null;
|
|
22624
|
+
}
|
|
22625
|
+
if (!/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/i.test(gstin.trim())) {
|
|
22626
|
+
return "Invalid GSTIN number (15 characters, e.g. 22AAAAA0000A1Z5)";
|
|
22627
|
+
}
|
|
22628
|
+
return null;
|
|
22629
|
+
}
|
|
22630
|
+
function validateIndiaTaxIds(gstin, pan, options) {
|
|
22631
|
+
const gstinErr = validateGstin(gstin, {
|
|
22632
|
+
required: options?.requiredGstin
|
|
22633
|
+
});
|
|
22634
|
+
if (gstinErr) return gstinErr;
|
|
22635
|
+
if (options?.requiredPan && (!pan || !pan.trim())) {
|
|
22636
|
+
return "PAN is required";
|
|
22637
|
+
}
|
|
22638
|
+
if (pan && !/^[A-Z]{5}[0-9]{4}[A-Z]$/i.test(pan.trim())) {
|
|
22324
22639
|
return "Invalid PAN format (e.g. ABCDE1234F)";
|
|
22325
22640
|
}
|
|
22326
22641
|
return null;
|
|
22327
22642
|
}
|
|
22328
22643
|
function validateAadhaar(aadhaar) {
|
|
22329
22644
|
if (!aadhaar) return null;
|
|
22330
|
-
if (!/^[0-9]{12}$/.test(aadhaar)) {
|
|
22645
|
+
if (!/^[0-9]{12}$/.test(aadhaar.replace(/\s+/g, ""))) {
|
|
22331
22646
|
return "Invalid Aadhaar number (12 digits)";
|
|
22332
22647
|
}
|
|
22333
22648
|
return null;
|
|
22334
22649
|
}
|
|
22335
22650
|
function validatePersonKyc(person, options) {
|
|
22336
22651
|
const required = options?.required === true;
|
|
22337
|
-
if (required && !person.aadhaarNo) return "Aadhaar number is required";
|
|
22338
|
-
if (required && !person.panNo) return "PAN is required";
|
|
22652
|
+
if (required && (!person.aadhaarNo || !person.aadhaarNo.trim())) return "Aadhaar number is required";
|
|
22653
|
+
if (required && (!person.panNo || !person.panNo.trim())) return "PAN is required";
|
|
22339
22654
|
const aadhaarErr = validateAadhaar(person.aadhaarNo ?? null);
|
|
22340
22655
|
if (aadhaarErr) return aadhaarErr;
|
|
22341
|
-
const panErr = validateIndiaTaxIds(null, person.panNo ?? null
|
|
22656
|
+
const panErr = validateIndiaTaxIds(null, person.panNo ?? null, {
|
|
22657
|
+
requiredPan: required
|
|
22658
|
+
});
|
|
22342
22659
|
if (panErr) return panErr;
|
|
22343
22660
|
return null;
|
|
22344
22661
|
}
|
|
22345
22662
|
function readOwnerDesignation(metadata) {
|
|
22346
|
-
|
|
22347
|
-
|
|
22663
|
+
if (!metadata || typeof metadata !== "object") return "";
|
|
22664
|
+
const d = metadata.ownerDesignation;
|
|
22665
|
+
return typeof d === "string" ? d.trim() : "";
|
|
22348
22666
|
}
|
|
22349
|
-
var VENDOR_REGISTRATION_STATUSES, VENDOR_BUSINESS_TYPES;
|
|
22667
|
+
var VENDOR_REGISTRATION_STATUSES, VENDOR_BUSINESS_TYPES, COUNTRY_PHONE_CODES;
|
|
22350
22668
|
var init_vendor_profile = __esm({
|
|
22351
22669
|
"src/lib/vendor-profile.ts"() {
|
|
22352
22670
|
VENDOR_REGISTRATION_STATUSES = [
|
|
@@ -22393,7 +22711,34 @@ var init_vendor_profile = __esm({
|
|
|
22393
22711
|
label: "Other"
|
|
22394
22712
|
}
|
|
22395
22713
|
];
|
|
22714
|
+
COUNTRY_PHONE_CODES = (() => {
|
|
22715
|
+
const list = [];
|
|
22716
|
+
const seenCodes = /* @__PURE__ */ new Set();
|
|
22717
|
+
for (const c of countryStateCity.Country.getAllCountries()) {
|
|
22718
|
+
if (!c.phonecode) continue;
|
|
22719
|
+
const rawCode = c.phonecode.replace(/^\+/, "").trim();
|
|
22720
|
+
if (!rawCode) continue;
|
|
22721
|
+
const code = `+${rawCode}`;
|
|
22722
|
+
const key = `${code}-${c.name}`;
|
|
22723
|
+
if (seenCodes.has(key)) continue;
|
|
22724
|
+
seenCodes.add(key);
|
|
22725
|
+
list.push({
|
|
22726
|
+
code,
|
|
22727
|
+
country: c.name,
|
|
22728
|
+
isoCode: c.isoCode,
|
|
22729
|
+
label: `${code} (${c.name})`
|
|
22730
|
+
});
|
|
22731
|
+
}
|
|
22732
|
+
return list.sort((a, b) => {
|
|
22733
|
+
if (a.code === "+91" && b.code !== "+91") return -1;
|
|
22734
|
+
if (b.code === "+91" && a.code !== "+91") return 1;
|
|
22735
|
+
return a.country.localeCompare(b.country);
|
|
22736
|
+
});
|
|
22737
|
+
})();
|
|
22738
|
+
__name(splitPhoneAndCountryCode, "splitPhoneAndCountryCode");
|
|
22739
|
+
__name(formatPhoneWithCountryCode, "formatPhoneWithCountryCode");
|
|
22396
22740
|
new Set(VENDOR_REGISTRATION_STATUSES.map((s) => s.value));
|
|
22741
|
+
__name(validateGstin, "validateGstin");
|
|
22397
22742
|
__name(validateIndiaTaxIds, "validateIndiaTaxIds");
|
|
22398
22743
|
__name(validateAadhaar, "validateAadhaar");
|
|
22399
22744
|
__name(validatePersonKyc, "validatePersonKyc");
|
|
@@ -22996,10 +23341,26 @@ function SubmissionDetailPage({ submissionId }) {
|
|
|
22996
23341
|
}
|
|
22997
23342
|
const formName = submission.form?.name ?? `Form #${submission.formId}`;
|
|
22998
23343
|
const contact = submission.contact;
|
|
22999
|
-
const
|
|
23000
|
-
|
|
23001
|
-
|
|
23002
|
-
|
|
23344
|
+
const resolveFieldLabel = /* @__PURE__ */ __name((key) => {
|
|
23345
|
+
if (!key) return "\u2014";
|
|
23346
|
+
const rawKey = key.trim();
|
|
23347
|
+
const numericIdMatch = rawKey.match(/^(?:field_)?(\d+)$/i);
|
|
23348
|
+
const fieldIdStr = numericIdMatch ? numericIdMatch[1] : null;
|
|
23349
|
+
const fields = submission?.form?.fields ?? [];
|
|
23350
|
+
const field = fields.find((f) => fieldIdStr !== null && String(f.id) === fieldIdStr || String(f.id) === rawKey || f.name && f.name.trim().toLowerCase() === rawKey.toLowerCase() || f.label && f.label.trim().toLowerCase() === rawKey.toLowerCase());
|
|
23351
|
+
if (field) {
|
|
23352
|
+
if (field.label && field.label.trim() && !/^\d+$/.test(field.label.trim())) {
|
|
23353
|
+
return field.label.trim();
|
|
23354
|
+
}
|
|
23355
|
+
if (field.name && field.name.trim() && !/^\d+$/.test(field.name.trim())) {
|
|
23356
|
+
return field.name.trim().replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
23357
|
+
}
|
|
23358
|
+
}
|
|
23359
|
+
if (fieldIdStr !== null) {
|
|
23360
|
+
return `Field #${fieldIdStr}`;
|
|
23361
|
+
}
|
|
23362
|
+
return rawKey.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
23363
|
+
}, "resolveFieldLabel");
|
|
23003
23364
|
return /* @__PURE__ */ React.createElement("div", {
|
|
23004
23365
|
className: "rounded-lg bg-white shadow-md"
|
|
23005
23366
|
}, /* @__PURE__ */ React.createElement(DetailPageHeader, {
|
|
@@ -23058,7 +23419,7 @@ function SubmissionDetailPage({ submissionId }) {
|
|
|
23058
23419
|
key
|
|
23059
23420
|
}, /* @__PURE__ */ React.createElement("td", {
|
|
23060
23421
|
className: "py-2 px-3 text-gray-600 font-medium"
|
|
23061
|
-
},
|
|
23422
|
+
}, resolveFieldLabel(key)), /* @__PURE__ */ React.createElement("td", {
|
|
23062
23423
|
className: "py-2 px-3 text-gray-900 break-words min-w-0"
|
|
23063
23424
|
}, value === null || value === void 0 ? "\u2014" : typeof value === "object" ? JSON.stringify(value) : String(value)))))))), /* @__PURE__ */ React.createElement("section", null, /* @__PURE__ */ React.createElement("h2", {
|
|
23064
23425
|
className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
|
|
@@ -24713,7 +25074,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
24713
25074
|
productQuery
|
|
24714
25075
|
]);
|
|
24715
25076
|
const recalcPreview = React25.useCallback(async () => {
|
|
24716
|
-
const orderLines = lines.filter((l) => !
|
|
25077
|
+
const orderLines = lines.filter((l) => !l.key.startsWith("reward-")).map((l) => ({
|
|
24717
25078
|
productId: l.productId,
|
|
24718
25079
|
quantity: l.quantity
|
|
24719
25080
|
}));
|
|
@@ -24737,19 +25098,22 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
24737
25098
|
body: JSON.stringify({
|
|
24738
25099
|
orderLines,
|
|
24739
25100
|
currency,
|
|
24740
|
-
discountId: coupons[0]?.discountId ?? null
|
|
25101
|
+
discountId: coupons[0]?.discountId ?? null,
|
|
25102
|
+
discountIds: coupons.map((c) => c.discountId)
|
|
24741
25103
|
})
|
|
24742
25104
|
});
|
|
24743
25105
|
if (!res.ok) throw new Error("Calculate failed");
|
|
24744
25106
|
const data = await res.json();
|
|
24745
25107
|
const correctedLines = data.lines.map((cl) => {
|
|
24746
25108
|
if (cl.productId == null) return cl;
|
|
24747
|
-
const
|
|
25109
|
+
const pid = Number(cl.productId);
|
|
25110
|
+
const cached = productCache.current.get(pid);
|
|
24748
25111
|
if (!cl.found && cached) {
|
|
24749
|
-
const unitPrice2 = cached.price;
|
|
25112
|
+
const unitPrice2 = Number(cached.price ?? 0);
|
|
24750
25113
|
const subtotal3 = unitPrice2 * cl.quantity;
|
|
24751
25114
|
return {
|
|
24752
25115
|
...cl,
|
|
25116
|
+
productId: pid,
|
|
24753
25117
|
found: true,
|
|
24754
25118
|
unitPrice: unitPrice2,
|
|
24755
25119
|
subtotal: subtotal3,
|
|
@@ -24757,15 +25121,16 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
24757
25121
|
total: subtotal3
|
|
24758
25122
|
};
|
|
24759
25123
|
}
|
|
24760
|
-
const unitPrice = cached?.price ?? cl.unitPrice;
|
|
25124
|
+
const unitPrice = Number(cached?.price ?? cl.unitPrice ?? 0);
|
|
24761
25125
|
const subtotal2 = unitPrice * cl.quantity;
|
|
24762
|
-
const taxRate = cl.taxRate ?? (cl.subtotal > 0 && cl.tax > 0 ? cl.tax / cl.subtotal : 0);
|
|
24763
|
-
const lineDiscount = cl.
|
|
25126
|
+
const taxRate = Number(cl.taxRate ?? (cl.subtotal > 0 && cl.tax > 0 ? cl.tax / cl.subtotal * 100 : 0));
|
|
25127
|
+
const lineDiscount = Number(cl.discount ?? 0);
|
|
24764
25128
|
const discountedBase = Math.max(0, subtotal2 - lineDiscount);
|
|
24765
25129
|
const tax2 = discountedBase * taxRate / 100;
|
|
24766
25130
|
const total2 = discountedBase + tax2;
|
|
24767
25131
|
return {
|
|
24768
25132
|
...cl,
|
|
25133
|
+
productId: pid,
|
|
24769
25134
|
unitPrice,
|
|
24770
25135
|
subtotal: subtotal2,
|
|
24771
25136
|
taxRate,
|
|
@@ -24773,13 +25138,14 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
24773
25138
|
total: total2
|
|
24774
25139
|
};
|
|
24775
25140
|
});
|
|
24776
|
-
const rewardDisplayLines = lines.filter((l) =>
|
|
24777
|
-
const
|
|
25141
|
+
const rewardDisplayLines = lines.filter((l) => l.key.startsWith("reward-")).map((l) => {
|
|
25142
|
+
const pid = Number(l.productId);
|
|
25143
|
+
const cached = productCache.current.get(pid);
|
|
24778
25144
|
return {
|
|
24779
|
-
productId:
|
|
25145
|
+
productId: pid,
|
|
24780
25146
|
productName: l.label,
|
|
24781
25147
|
found: true,
|
|
24782
|
-
unitPrice: cached?.price ?? 0,
|
|
25148
|
+
unitPrice: Number(cached?.price ?? 0),
|
|
24783
25149
|
quantity: l.quantity,
|
|
24784
25150
|
subtotal: 0,
|
|
24785
25151
|
tax: 0,
|
|
@@ -24821,7 +25187,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
24821
25187
|
React25.useEffect(() => {
|
|
24822
25188
|
const automaticCoupons = coupons.filter((c) => c.isAutomatic);
|
|
24823
25189
|
if (automaticCoupons.length === 0) return;
|
|
24824
|
-
const nonRewardLines = lines.filter((l) => !
|
|
25190
|
+
const nonRewardLines = lines.filter((l) => !l.key.startsWith("reward-"));
|
|
24825
25191
|
if (nonRewardLines.length === 0) {
|
|
24826
25192
|
const autoIds = new Set(automaticCoupons.map((c) => c.discountId));
|
|
24827
25193
|
const rewardPids = new Set(automaticCoupons.flatMap((c) => c.rewardLines.map((r) => r.productId)));
|
|
@@ -24901,7 +25267,7 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
24901
25267
|
cancelled = true;
|
|
24902
25268
|
};
|
|
24903
25269
|
}, [
|
|
24904
|
-
lines.filter((l) => !
|
|
25270
|
+
lines.filter((l) => !l.key.startsWith("reward-")).map((l) => `${l.productId}:${l.quantity}`).join(","),
|
|
24905
25271
|
coupons.filter((c) => c.isAutomatic).map((c) => c.discountId).join(",")
|
|
24906
25272
|
]);
|
|
24907
25273
|
function handleRemoveCoupon(couponCode) {
|
|
@@ -25023,7 +25389,10 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
25023
25389
|
const calcByProductId = React25.useMemo(() => {
|
|
25024
25390
|
const m = /* @__PURE__ */ new Map();
|
|
25025
25391
|
for (const l of preview?.lines ?? []) {
|
|
25026
|
-
if (l.productId != null && l.found)
|
|
25392
|
+
if (l.productId != null && l.found) {
|
|
25393
|
+
const pid = Number(l.productId);
|
|
25394
|
+
if (Number.isFinite(pid)) m.set(pid, l);
|
|
25395
|
+
}
|
|
25027
25396
|
}
|
|
25028
25397
|
return m;
|
|
25029
25398
|
}, [
|
|
@@ -25045,13 +25414,13 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
25045
25414
|
}
|
|
25046
25415
|
const unknown = preview?.lines.filter((l) => !l.found) ?? [];
|
|
25047
25416
|
if (unknown.length > 0) {
|
|
25048
|
-
sonner.toast.error(
|
|
25417
|
+
sonner.toast.error(`One or more items could not be validated: ${unknown.map((u) => u.productName).join(", ")}`);
|
|
25049
25418
|
return;
|
|
25050
25419
|
}
|
|
25051
25420
|
setSubmitting(true);
|
|
25421
|
+
let resolvedContactId = effectiveContactId;
|
|
25052
25422
|
try {
|
|
25053
|
-
|
|
25054
|
-
if (!resolvedContactId && effectiveEmail) {
|
|
25423
|
+
if (resolvedContactId == null && effectiveEmail) {
|
|
25055
25424
|
try {
|
|
25056
25425
|
const res2 = await fetch(`/api/contacts?search=${encodeURIComponent(effectiveEmail)}&limit=1`);
|
|
25057
25426
|
if (res2.ok) {
|
|
@@ -25073,12 +25442,12 @@ function OrderPlacementPage({ editOrderId }) {
|
|
|
25073
25442
|
billingAddress,
|
|
25074
25443
|
shippingAddress: sameAsBilling ? billingAddress : shippingAddress,
|
|
25075
25444
|
orderLines: lines.map((l) => {
|
|
25076
|
-
const isReward =
|
|
25077
|
-
const calc = preview?.lines.find((pl) => pl.productId === l.productId);
|
|
25445
|
+
const isReward = l.key.startsWith("reward-");
|
|
25446
|
+
const calc = preview?.lines.find((pl) => Number(pl.productId) === Number(l.productId));
|
|
25078
25447
|
return {
|
|
25079
25448
|
productId: l.productId,
|
|
25080
25449
|
quantity: l.quantity,
|
|
25081
|
-
unitPrice: isReward ? 0 : calc?.unitPrice ?? productCache.current.get(l.productId)?.price ?? 0
|
|
25450
|
+
unitPrice: isReward ? 0 : calc?.unitPrice ?? Number(productCache.current.get(l.productId)?.price ?? 0)
|
|
25082
25451
|
};
|
|
25083
25452
|
})
|
|
25084
25453
|
};
|
|
@@ -30054,8 +30423,8 @@ function ProductEditPage({ productId }) {
|
|
|
30054
30423
|
const [price, setPrice] = React25.useState(0);
|
|
30055
30424
|
const [defaultPriceStr, setDefaultPriceStr] = React25.useState("");
|
|
30056
30425
|
const [pricingConfig, setPricingConfig] = React25.useState(DEFAULT_PRICING_CONFIG);
|
|
30057
|
-
const [compareAtPrice, setCompareAtPrice] = React25.useState(
|
|
30058
|
-
const [quantity, setQuantity] = React25.useState(1);
|
|
30426
|
+
const [compareAtPrice, setCompareAtPrice] = React25.useState("");
|
|
30427
|
+
const [quantity, setQuantity] = React25.useState("1");
|
|
30059
30428
|
const [status, setStatus] = React25.useState("draft");
|
|
30060
30429
|
const [approvalStatus, setApprovalStatus] = React25.useState("pending");
|
|
30061
30430
|
const [rejectionReason, setRejectionReason] = React25.useState("");
|
|
@@ -30276,8 +30645,8 @@ function ProductEditPage({ productId }) {
|
|
|
30276
30645
|
setDefaultPriceStr(product.price != null && Number.isFinite(Number(product.price)) ? String(product.price) : "");
|
|
30277
30646
|
setPrice(product.price != null ? Number(product.price) : 0);
|
|
30278
30647
|
const rawCompare = product.compareAtPrice != null ? Number(product.compareAtPrice) : 0;
|
|
30279
|
-
setCompareAtPrice(Number.isFinite(rawCompare) ? rawCompare :
|
|
30280
|
-
setQuantity(product.quantity
|
|
30648
|
+
setCompareAtPrice(rawCompare != null && Number.isFinite(rawCompare) ? String(rawCompare) : "");
|
|
30649
|
+
setQuantity(product.quantity != null ? String(product.quantity) : "1");
|
|
30281
30650
|
setStatus(product.status ?? "draft");
|
|
30282
30651
|
setApprovalStatus(typeof product.approvalStatus === "string" && product.approvalStatus ? product.approvalStatus : "pending");
|
|
30283
30652
|
setRejectionReason(typeof product.rejectionReason === "string" ? product.rejectionReason : "");
|
|
@@ -30444,22 +30813,6 @@ function ProductEditPage({ productId }) {
|
|
|
30444
30813
|
return pricingConfig.defaultCurrency || "INR";
|
|
30445
30814
|
}
|
|
30446
30815
|
})();
|
|
30447
|
-
const handleNumberChange = /* @__PURE__ */ __name((setter, options) => (e) => {
|
|
30448
|
-
const value = e.target.value;
|
|
30449
|
-
if (value === "") {
|
|
30450
|
-
setter(0);
|
|
30451
|
-
return;
|
|
30452
|
-
}
|
|
30453
|
-
let num = options?.integer ? Number.parseInt(value, 10) : Number(value);
|
|
30454
|
-
if (Number.isNaN(num)) {
|
|
30455
|
-
setter(0);
|
|
30456
|
-
return;
|
|
30457
|
-
}
|
|
30458
|
-
if (options?.min !== void 0) {
|
|
30459
|
-
num = Math.max(options.min, num);
|
|
30460
|
-
}
|
|
30461
|
-
setter(num);
|
|
30462
|
-
}, "handleNumberChange");
|
|
30463
30816
|
const openRejectModal = /* @__PURE__ */ __name((fromStatus) => {
|
|
30464
30817
|
approvalBeforeRejectRef.current = fromStatus === "rejected" ? "pending" : fromStatus;
|
|
30465
30818
|
setRejectDraft(rejectionReason);
|
|
@@ -30532,12 +30885,13 @@ function ProductEditPage({ productId }) {
|
|
|
30532
30885
|
return;
|
|
30533
30886
|
}
|
|
30534
30887
|
}
|
|
30535
|
-
const
|
|
30888
|
+
const quantityValue = quantity === "" ? 0 : Number(quantity);
|
|
30889
|
+
const quantityErrors = validateProductQuantity(quantityValue, hasVariants, parsedVariants);
|
|
30536
30890
|
if (quantityErrors.length) {
|
|
30537
30891
|
setErrors(quantityErrors);
|
|
30538
30892
|
return;
|
|
30539
30893
|
}
|
|
30540
|
-
const resolvedQuantity = hasVariants ? productQuantityFromVariants(parsedVariants) :
|
|
30894
|
+
const resolvedQuantity = hasVariants ? productQuantityFromVariants(parsedVariants) : quantityValue;
|
|
30541
30895
|
setSaving(true);
|
|
30542
30896
|
try {
|
|
30543
30897
|
const compareAtPriceValue = compareAtPrice ? Math.round(Number(compareAtPrice) * 100) / 100 : null;
|
|
@@ -31151,9 +31505,8 @@ function ProductEditPage({ productId }) {
|
|
|
31151
31505
|
type: "number",
|
|
31152
31506
|
value: compareAtPrice,
|
|
31153
31507
|
className: inputCls3,
|
|
31154
|
-
|
|
31155
|
-
|
|
31156
|
-
})
|
|
31508
|
+
min: 0,
|
|
31509
|
+
onChange: /* @__PURE__ */ __name((e) => setCompareAtPrice(e.target.value), "onChange")
|
|
31157
31510
|
})), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
|
|
31158
31511
|
className: labelCls3
|
|
31159
31512
|
}, "Contact form"), /* @__PURE__ */ React.createElement("select", {
|
|
@@ -31176,10 +31529,7 @@ function ProductEditPage({ productId }) {
|
|
|
31176
31529
|
min: 0,
|
|
31177
31530
|
step: 1,
|
|
31178
31531
|
value: hasVariants ? productQuantityFromVariants(variantsFromForm(variantRows, pricingConfig.defaultCurrency)) : quantity,
|
|
31179
|
-
onChange:
|
|
31180
|
-
min: 0,
|
|
31181
|
-
integer: true
|
|
31182
|
-
}),
|
|
31532
|
+
onChange: /* @__PURE__ */ __name((e) => setQuantity(e.target.value), "onChange"),
|
|
31183
31533
|
className: `${inputCls3}${hasVariants ? " bg-gray-100" : ""}`,
|
|
31184
31534
|
required: !hasVariants,
|
|
31185
31535
|
readOnly: hasVariants,
|
|
@@ -31256,8 +31606,18 @@ function ProductEditPage({ productId }) {
|
|
|
31256
31606
|
value: row.taxId === "" ? "" : String(row.taxId),
|
|
31257
31607
|
onChange: /* @__PURE__ */ __name((e) => {
|
|
31258
31608
|
const v = e.target.value;
|
|
31609
|
+
if (v === "") {
|
|
31610
|
+
setTaxRow(i, {
|
|
31611
|
+
taxId: "",
|
|
31612
|
+
rate: ""
|
|
31613
|
+
});
|
|
31614
|
+
return;
|
|
31615
|
+
}
|
|
31616
|
+
const taxId = Number(v);
|
|
31617
|
+
const selectedTax = taxMasterList.find((t) => t.id === taxId);
|
|
31259
31618
|
setTaxRow(i, {
|
|
31260
|
-
taxId
|
|
31619
|
+
taxId,
|
|
31620
|
+
rate: selectedTax?.rate != null ? String(selectedTax.rate) : ""
|
|
31261
31621
|
});
|
|
31262
31622
|
}, "onChange"),
|
|
31263
31623
|
className: inputCls3
|
|
@@ -33082,6 +33442,35 @@ function EventEditPage({ eventId }) {
|
|
|
33082
33442
|
const [saving, setSaving] = React25.useState(false);
|
|
33083
33443
|
const [errors, setErrors] = React25.useState([]);
|
|
33084
33444
|
const [activeTab, setActiveTab] = React25.useState("basic");
|
|
33445
|
+
const eventTabs = [
|
|
33446
|
+
{
|
|
33447
|
+
key: "basic",
|
|
33448
|
+
label: "Basic info"
|
|
33449
|
+
},
|
|
33450
|
+
{
|
|
33451
|
+
key: "venue",
|
|
33452
|
+
label: "Venue"
|
|
33453
|
+
},
|
|
33454
|
+
{
|
|
33455
|
+
key: "datetime",
|
|
33456
|
+
label: "Date & time"
|
|
33457
|
+
},
|
|
33458
|
+
{
|
|
33459
|
+
key: "settings",
|
|
33460
|
+
label: "Settings"
|
|
33461
|
+
}
|
|
33462
|
+
];
|
|
33463
|
+
const activeTabIndex = eventTabs.findIndex((tab) => tab.key === activeTab);
|
|
33464
|
+
const goToPreviousTab = /* @__PURE__ */ __name(() => {
|
|
33465
|
+
if (activeTabIndex > 0) {
|
|
33466
|
+
setActiveTab(eventTabs[activeTabIndex - 1].key);
|
|
33467
|
+
}
|
|
33468
|
+
}, "goToPreviousTab");
|
|
33469
|
+
const goToNextTab = /* @__PURE__ */ __name(() => {
|
|
33470
|
+
if (activeTabIndex < eventTabs.length - 1) {
|
|
33471
|
+
setActiveTab(eventTabs[activeTabIndex + 1].key);
|
|
33472
|
+
}
|
|
33473
|
+
}, "goToNextTab");
|
|
33085
33474
|
const [name, setName] = React25.useState("");
|
|
33086
33475
|
const [slug, setSlug] = React25.useState("");
|
|
33087
33476
|
const [description, setDescription] = React25.useState("");
|
|
@@ -33901,7 +34290,19 @@ function EventEditPage({ eventId }) {
|
|
|
33901
34290
|
[key]: value
|
|
33902
34291
|
})), "onChange")
|
|
33903
34292
|
}))))
|
|
33904
|
-
}),
|
|
34293
|
+
}), /* @__PURE__ */ React.createElement("div", {
|
|
34294
|
+
className: "flex items-center justify-between border-t border-gray-200 px-4 py-4 sm:px-6"
|
|
34295
|
+
}, /* @__PURE__ */ React.createElement("button", {
|
|
34296
|
+
type: "button",
|
|
34297
|
+
onClick: goToPreviousTab,
|
|
34298
|
+
disabled: activeTabIndex === 0,
|
|
34299
|
+
className: "rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-40"
|
|
34300
|
+
}, "Previous"), /* @__PURE__ */ React.createElement("button", {
|
|
34301
|
+
type: "button",
|
|
34302
|
+
onClick: goToNextTab,
|
|
34303
|
+
disabled: activeTabIndex === eventTabs.length - 1,
|
|
34304
|
+
className: "rounded-md bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-40"
|
|
34305
|
+
}, "Next")), showEventProducts ? /* @__PURE__ */ React.createElement("div", {
|
|
33905
34306
|
className: "border-t border-gray-200 px-4 py-4 sm:px-6"
|
|
33906
34307
|
}, /* @__PURE__ */ React.createElement(EventProductsSection, {
|
|
33907
34308
|
eventId: eventRecordId,
|
|
@@ -34246,6 +34647,18 @@ function ComboEditPage({ comboId }) {
|
|
|
34246
34647
|
]);
|
|
34247
34648
|
return;
|
|
34248
34649
|
}
|
|
34650
|
+
if (!startsAt) {
|
|
34651
|
+
setErrors([
|
|
34652
|
+
"Starts at is required"
|
|
34653
|
+
]);
|
|
34654
|
+
return;
|
|
34655
|
+
}
|
|
34656
|
+
if (!endsAt) {
|
|
34657
|
+
setErrors([
|
|
34658
|
+
"Ends at is required"
|
|
34659
|
+
]);
|
|
34660
|
+
return;
|
|
34661
|
+
}
|
|
34249
34662
|
if (!priceStr.trim()) {
|
|
34250
34663
|
setErrors([
|
|
34251
34664
|
`Price (${defaultCurrency}) is required`
|
|
@@ -34535,18 +34948,20 @@ function ComboEditPage({ comboId }) {
|
|
|
34535
34948
|
className: "grid grid-cols-2 gap-4"
|
|
34536
34949
|
}, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
|
|
34537
34950
|
className: "block text-xs font-medium text-gray-600 mb-1"
|
|
34538
|
-
}, "Starts at"), /* @__PURE__ */ React.createElement("input", {
|
|
34951
|
+
}, "Starts at *"), /* @__PURE__ */ React.createElement("input", {
|
|
34539
34952
|
type: "datetime-local",
|
|
34540
34953
|
value: startsAt,
|
|
34541
34954
|
onChange: /* @__PURE__ */ __name((e) => setStartsAt(e.target.value), "onChange"),
|
|
34542
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
34955
|
+
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm",
|
|
34956
|
+
required: true
|
|
34543
34957
|
})), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("label", {
|
|
34544
34958
|
className: "block text-xs font-medium text-gray-600 mb-1"
|
|
34545
|
-
}, "Ends at"), /* @__PURE__ */ React.createElement("input", {
|
|
34959
|
+
}, "Ends at *"), /* @__PURE__ */ React.createElement("input", {
|
|
34546
34960
|
type: "datetime-local",
|
|
34547
34961
|
value: endsAt,
|
|
34548
34962
|
onChange: /* @__PURE__ */ __name((e) => setEndsAt(e.target.value), "onChange"),
|
|
34549
|
-
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
|
|
34963
|
+
className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm",
|
|
34964
|
+
required: true
|
|
34550
34965
|
})))))),
|
|
34551
34966
|
sidebar: /* @__PURE__ */ React.createElement(React.Fragment, null)
|
|
34552
34967
|
}));
|
|
@@ -34632,7 +35047,8 @@ function VendorEditPage({ vendorId }) {
|
|
|
34632
35047
|
const [website, setWebsite] = React25.useState("");
|
|
34633
35048
|
const [logo, setLogo] = React25.useState("");
|
|
34634
35049
|
const [email, setEmail] = React25.useState("");
|
|
34635
|
-
const [
|
|
35050
|
+
const [storePhoneCode, setStorePhoneCode] = React25.useState("+91");
|
|
35051
|
+
const [storePhoneNum, setStorePhoneNum] = React25.useState("");
|
|
34636
35052
|
const [addressLine1, setAddressLine1] = React25.useState("");
|
|
34637
35053
|
const [addressLine2, setAddressLine2] = React25.useState("");
|
|
34638
35054
|
const [city, setCity] = React25.useState("");
|
|
@@ -34646,7 +35062,8 @@ function VendorEditPage({ vendorId }) {
|
|
|
34646
35062
|
const [metadata, setMetadata] = React25.useState(null);
|
|
34647
35063
|
const [ownerName, setOwnerName] = React25.useState("");
|
|
34648
35064
|
const [ownerEmail, setOwnerEmail] = React25.useState("");
|
|
34649
|
-
const [
|
|
35065
|
+
const [ownerPhoneCode, setOwnerPhoneCode] = React25.useState("+91");
|
|
35066
|
+
const [ownerPhoneNum, setOwnerPhoneNum] = React25.useState("");
|
|
34650
35067
|
const [ownerDesignation, setOwnerDesignation] = React25.useState("");
|
|
34651
35068
|
const [ownerAadhaarNo, setOwnerAadhaarNo] = React25.useState("");
|
|
34652
35069
|
const [ownerPanNo, setOwnerPanNo] = React25.useState("");
|
|
@@ -34670,7 +35087,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
34670
35087
|
website: website.trim() || null,
|
|
34671
35088
|
logo: logo.trim() || null,
|
|
34672
35089
|
email: email.trim() || null,
|
|
34673
|
-
phone:
|
|
35090
|
+
phone: formatPhoneWithCountryCode(storePhoneCode, storePhoneNum),
|
|
34674
35091
|
addressLine1: addressLine1.trim() || null,
|
|
34675
35092
|
addressLine2: addressLine2.trim() || null,
|
|
34676
35093
|
city: city.trim() || null,
|
|
@@ -34698,7 +35115,9 @@ function VendorEditPage({ vendorId }) {
|
|
|
34698
35115
|
setWebsite(data.website ?? "");
|
|
34699
35116
|
setLogo(data.logo ?? "");
|
|
34700
35117
|
setEmail(data.email ?? "");
|
|
34701
|
-
|
|
35118
|
+
const sPhone = splitPhoneAndCountryCode(data.phone);
|
|
35119
|
+
setStorePhoneCode(sPhone.countryCode);
|
|
35120
|
+
setStorePhoneNum(sPhone.phoneNumber);
|
|
34702
35121
|
setAddressLine1(data.addressLine1 ?? "");
|
|
34703
35122
|
setAddressLine2(data.addressLine2 ?? "");
|
|
34704
35123
|
setCity(data.city ?? "");
|
|
@@ -34720,7 +35139,9 @@ function VendorEditPage({ vendorId }) {
|
|
|
34720
35139
|
if (!cancelled) {
|
|
34721
35140
|
setOwnerName(user.name ?? "");
|
|
34722
35141
|
setOwnerEmail(user.email ?? "");
|
|
34723
|
-
|
|
35142
|
+
const oPhone = splitPhoneAndCountryCode(user.phone);
|
|
35143
|
+
setOwnerPhoneCode(oPhone.countryCode);
|
|
35144
|
+
setOwnerPhoneNum(oPhone.phoneNumber);
|
|
34724
35145
|
}
|
|
34725
35146
|
}
|
|
34726
35147
|
} else if (!cancelled) {
|
|
@@ -34867,7 +35288,10 @@ function VendorEditPage({ vendorId }) {
|
|
|
34867
35288
|
setSaving(false);
|
|
34868
35289
|
return;
|
|
34869
35290
|
}
|
|
34870
|
-
const
|
|
35291
|
+
const formattedOwnerPhone = formatPhoneWithCountryCode(ownerPhoneCode, ownerPhoneNum);
|
|
35292
|
+
const taxError = validateGstin(gstin.trim().toUpperCase() || null, {
|
|
35293
|
+
required: true
|
|
35294
|
+
});
|
|
34871
35295
|
if (taxError) {
|
|
34872
35296
|
setErrors([
|
|
34873
35297
|
taxError
|
|
@@ -34909,7 +35333,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
34909
35333
|
user: {
|
|
34910
35334
|
name: ownerName.trim(),
|
|
34911
35335
|
email: ownerEmail.trim(),
|
|
34912
|
-
phone:
|
|
35336
|
+
phone: formattedOwnerPhone || void 0,
|
|
34913
35337
|
designation: ownerDesignation.trim() || void 0,
|
|
34914
35338
|
aadhaarNo: ownerAadhaarNo.trim(),
|
|
34915
35339
|
panNo: ownerPanNo.trim().toUpperCase(),
|
|
@@ -34973,7 +35397,9 @@ function VendorEditPage({ vendorId }) {
|
|
|
34973
35397
|
setSaving(false);
|
|
34974
35398
|
return;
|
|
34975
35399
|
}
|
|
34976
|
-
const taxError =
|
|
35400
|
+
const taxError = validateGstin(gstin.trim().toUpperCase() || null, {
|
|
35401
|
+
required: false
|
|
35402
|
+
});
|
|
34977
35403
|
if (taxError) {
|
|
34978
35404
|
setErrors([
|
|
34979
35405
|
taxError
|
|
@@ -35009,6 +35435,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35009
35435
|
return;
|
|
35010
35436
|
}
|
|
35011
35437
|
if (ownerUserId != null) {
|
|
35438
|
+
const formattedOwnerPhone = formatPhoneWithCountryCode(ownerPhoneCode, ownerPhoneNum);
|
|
35012
35439
|
const userRes = await fetch(`/api/users/${ownerUserId}`, {
|
|
35013
35440
|
method: "PUT",
|
|
35014
35441
|
headers: {
|
|
@@ -35017,7 +35444,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35017
35444
|
body: JSON.stringify({
|
|
35018
35445
|
name: ownerName.trim(),
|
|
35019
35446
|
email: ownerEmail.trim(),
|
|
35020
|
-
phone:
|
|
35447
|
+
phone: formattedOwnerPhone || null
|
|
35021
35448
|
})
|
|
35022
35449
|
});
|
|
35023
35450
|
if (!userRes.ok) {
|
|
@@ -35151,12 +35578,23 @@ function VendorEditPage({ vendorId }) {
|
|
|
35151
35578
|
className: `mt-1 ${fieldClass}`
|
|
35152
35579
|
})), /* @__PURE__ */ React25__namespace.default.createElement("div", null, /* @__PURE__ */ React25__namespace.default.createElement(FieldLabel, {
|
|
35153
35580
|
htmlFor: "vendorPhone"
|
|
35154
|
-
}, "Store phone"), /* @__PURE__ */ React25__namespace.default.createElement(
|
|
35581
|
+
}, "Store phone"), /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
35582
|
+
className: "flex gap-2 mt-1"
|
|
35583
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("select", {
|
|
35584
|
+
value: storePhoneCode,
|
|
35585
|
+
onChange: /* @__PURE__ */ __name((e) => setStorePhoneCode(e.target.value), "onChange"),
|
|
35586
|
+
className: "w-36 rounded-md border border-gray-300 px-3 py-2 text-sm bg-white focus:outline-none focus:ring-1 focus:ring-black"
|
|
35587
|
+
}, COUNTRY_PHONE_CODES.map((c) => /* @__PURE__ */ React25__namespace.default.createElement("option", {
|
|
35588
|
+
key: c.code,
|
|
35589
|
+
value: c.code
|
|
35590
|
+
}, c.label))), /* @__PURE__ */ React25__namespace.default.createElement(Input, {
|
|
35155
35591
|
id: "vendorPhone",
|
|
35156
|
-
|
|
35157
|
-
|
|
35158
|
-
|
|
35159
|
-
|
|
35592
|
+
type: "tel",
|
|
35593
|
+
placeholder: "9876543210",
|
|
35594
|
+
value: storePhoneNum,
|
|
35595
|
+
onChange: /* @__PURE__ */ __name((e) => setStorePhoneNum(e.target.value.replace(/\D/g, "")), "onChange"),
|
|
35596
|
+
className: `flex-1 ${fieldClass}`
|
|
35597
|
+
}))))), /* @__PURE__ */ React25__namespace.default.createElement("section", null, /* @__PURE__ */ React25__namespace.default.createElement("h2", {
|
|
35160
35598
|
className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
|
|
35161
35599
|
}, "Store address"), /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
35162
35600
|
className: sectionCls5
|
|
@@ -35209,12 +35647,15 @@ function VendorEditPage({ vendorId }) {
|
|
|
35209
35647
|
className: `mt-1 ${fieldClass}`
|
|
35210
35648
|
}))))), /* @__PURE__ */ React25__namespace.default.createElement("section", null, /* @__PURE__ */ React25__namespace.default.createElement("h2", {
|
|
35211
35649
|
className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
|
|
35212
|
-
}, "Tax
|
|
35650
|
+
}, "Tax"), /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
35213
35651
|
className: sectionCls5
|
|
35214
35652
|
}, /* @__PURE__ */ React25__namespace.default.createElement("div", null, /* @__PURE__ */ React25__namespace.default.createElement(FieldLabel, {
|
|
35215
|
-
htmlFor: "gstin"
|
|
35653
|
+
htmlFor: "gstin",
|
|
35654
|
+
required: create
|
|
35216
35655
|
}, "GSTIN"), /* @__PURE__ */ React25__namespace.default.createElement(Input, {
|
|
35217
35656
|
id: "gstin",
|
|
35657
|
+
required: create,
|
|
35658
|
+
maxLength: 15,
|
|
35218
35659
|
value: gstin,
|
|
35219
35660
|
onChange: /* @__PURE__ */ __name((e) => setGstin(e.target.value.toUpperCase()), "onChange"),
|
|
35220
35661
|
placeholder: "22AAAAA0000A1Z5",
|
|
@@ -35244,12 +35685,23 @@ function VendorEditPage({ vendorId }) {
|
|
|
35244
35685
|
className: `mt-1 ${fieldClass}`
|
|
35245
35686
|
})), /* @__PURE__ */ React25__namespace.default.createElement("div", null, /* @__PURE__ */ React25__namespace.default.createElement(FieldLabel, {
|
|
35246
35687
|
htmlFor: "ownerPhone"
|
|
35247
|
-
}, "Phone"), /* @__PURE__ */ React25__namespace.default.createElement(
|
|
35688
|
+
}, "Phone"), /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
35689
|
+
className: "flex gap-2 mt-1"
|
|
35690
|
+
}, /* @__PURE__ */ React25__namespace.default.createElement("select", {
|
|
35691
|
+
value: ownerPhoneCode,
|
|
35692
|
+
onChange: /* @__PURE__ */ __name((e) => setOwnerPhoneCode(e.target.value), "onChange"),
|
|
35693
|
+
className: "w-36 rounded-md border border-gray-300 px-3 py-2 text-sm bg-white focus:outline-none focus:ring-1 focus:ring-black"
|
|
35694
|
+
}, COUNTRY_PHONE_CODES.map((c) => /* @__PURE__ */ React25__namespace.default.createElement("option", {
|
|
35695
|
+
key: c.code,
|
|
35696
|
+
value: c.code
|
|
35697
|
+
}, c.label))), /* @__PURE__ */ React25__namespace.default.createElement(Input, {
|
|
35248
35698
|
id: "ownerPhone",
|
|
35249
|
-
|
|
35250
|
-
|
|
35251
|
-
|
|
35252
|
-
|
|
35699
|
+
type: "tel",
|
|
35700
|
+
placeholder: "9876543210",
|
|
35701
|
+
value: ownerPhoneNum,
|
|
35702
|
+
onChange: /* @__PURE__ */ __name((e) => setOwnerPhoneNum(e.target.value.replace(/\D/g, "")), "onChange"),
|
|
35703
|
+
className: `flex-1 ${fieldClass}`
|
|
35704
|
+
}))), /* @__PURE__ */ React25__namespace.default.createElement("div", null, /* @__PURE__ */ React25__namespace.default.createElement(FieldLabel, {
|
|
35253
35705
|
htmlFor: "ownerDesignation"
|
|
35254
35706
|
}, "Designation"), /* @__PURE__ */ React25__namespace.default.createElement(Input, {
|
|
35255
35707
|
id: "ownerDesignation",
|
|
@@ -35334,7 +35786,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35334
35786
|
htmlFor: "termsAccepted",
|
|
35335
35787
|
className: "font-normal cursor-pointer text-sm leading-snug"
|
|
35336
35788
|
}, "I confirm I have read and accepted the terms and conditions for selling on this platform."))))),
|
|
35337
|
-
sidebar:
|
|
35789
|
+
sidebar: create ? void 0 : /* @__PURE__ */ React25__namespace.default.createElement("section", null, /* @__PURE__ */ React25__namespace.default.createElement("h2", {
|
|
35338
35790
|
className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
|
|
35339
35791
|
}, "Status"), /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
35340
35792
|
className: sectionCls5
|
|
@@ -35369,18 +35821,7 @@ function VendorEditPage({ vendorId }) {
|
|
|
35369
35821
|
readOnly: true,
|
|
35370
35822
|
value: active ? "Yes" : "No",
|
|
35371
35823
|
className: `mt-1 ${fieldClass} bg-gray-100`
|
|
35372
|
-
}))))
|
|
35373
|
-
className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2"
|
|
35374
|
-
}, "Owner access"), /* @__PURE__ */ React25__namespace.default.createElement("div", {
|
|
35375
|
-
className: sectionCls5
|
|
35376
|
-
}, /* @__PURE__ */ React25__namespace.default.createElement("p", {
|
|
35377
|
-
className: "text-sm text-gray-600"
|
|
35378
|
-
}, "Creates the vendor and an invite for the owner. After create, you can send the invite email or copy the invite link."), /* @__PURE__ */ React25__namespace.default.createElement(Button, {
|
|
35379
|
-
type: "button",
|
|
35380
|
-
disabled: saving,
|
|
35381
|
-
onClick: handleCreate,
|
|
35382
|
-
className: "w-full"
|
|
35383
|
-
}, saving ? "Creating\u2026" : "Create vendor"))) : void 0)
|
|
35824
|
+
}))))
|
|
35384
35825
|
}), /* @__PURE__ */ React25__namespace.default.createElement(Dialog, {
|
|
35385
35826
|
open: inviteDialog != null,
|
|
35386
35827
|
onOpenChange: /* @__PURE__ */ __name((open) => {
|
|
@@ -36975,7 +37416,7 @@ function ConditionCard({ condition, onChange, onRemove, eventsOn }) {
|
|
|
36975
37416
|
value: "minAmount"
|
|
36976
37417
|
}, "Minimum order amount"), /* @__PURE__ */ React.createElement(SelectItem, {
|
|
36977
37418
|
value: "minQuantity"
|
|
36978
|
-
}, "Minimum
|
|
37419
|
+
}, "Minimum Cart Quantity"), /* @__PURE__ */ React.createElement(SelectItem, {
|
|
36979
37420
|
value: "productMinQuantity"
|
|
36980
37421
|
}, "Product"), (eventsOn || condition.kind === "events") && /* @__PURE__ */ React.createElement(SelectItem, {
|
|
36981
37422
|
value: "events"
|
|
@@ -38430,8 +38871,8 @@ function ContactDetailPage({ contactId }) {
|
|
|
38430
38871
|
setAddAddressError("Select country, state, and city from the lists.");
|
|
38431
38872
|
return;
|
|
38432
38873
|
}
|
|
38433
|
-
const { Country:
|
|
38434
|
-
const countryName =
|
|
38874
|
+
const { Country: Country3, State: State2 } = await import('country-state-city');
|
|
38875
|
+
const countryName = Country3.getCountryByCode(addressGeo.countryIso)?.name ?? "";
|
|
38435
38876
|
const stateName = State2.getStatesOfCountry(addressGeo.countryIso).find((s) => s.isoCode === addressGeo.stateIso)?.name ?? "";
|
|
38436
38877
|
const payload = {
|
|
38437
38878
|
contactId: Number(contactId),
|