order-management 0.0.104 → 0.0.105
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.
|
@@ -924,1295 +924,6 @@ const OrderRefundContextWidget = (props) => {
|
|
|
924
924
|
adminSdk.defineWidgetConfig({
|
|
925
925
|
zone: "order.details.after"
|
|
926
926
|
});
|
|
927
|
-
const AUDITED_TABLE_NAMES = [
|
|
928
|
-
"account_deletion_request",
|
|
929
|
-
"account_holder",
|
|
930
|
-
"api_key",
|
|
931
|
-
"application_method_buy_rules",
|
|
932
|
-
"application_method_target_rules",
|
|
933
|
-
"auth_identity",
|
|
934
|
-
"auth_mfa_factor",
|
|
935
|
-
"auth_mfa_recovery_code",
|
|
936
|
-
"auth_password_reset_token",
|
|
937
|
-
"auth_verification",
|
|
938
|
-
"cancel_order_reason_mapping",
|
|
939
|
-
"capture",
|
|
940
|
-
"cart",
|
|
941
|
-
"cart_address",
|
|
942
|
-
"cart_line_item",
|
|
943
|
-
"cart_line_item_adjustment",
|
|
944
|
-
"cart_line_item_tax_line",
|
|
945
|
-
"cart_payment_collection",
|
|
946
|
-
"cart_promotion",
|
|
947
|
-
"cart_shipping_method",
|
|
948
|
-
"cart_shipping_method_adjustment",
|
|
949
|
-
"cart_shipping_method_tax_line",
|
|
950
|
-
"contact_email_subscription",
|
|
951
|
-
"contact_request",
|
|
952
|
-
"contact_request_comment",
|
|
953
|
-
"credit_line",
|
|
954
|
-
"currency",
|
|
955
|
-
"customer",
|
|
956
|
-
"customer_account_holder",
|
|
957
|
-
"customer_address",
|
|
958
|
-
"customer_group",
|
|
959
|
-
"customer_group_customer",
|
|
960
|
-
"dynamic_config_value",
|
|
961
|
-
"fulfillment",
|
|
962
|
-
"fulfillment_address",
|
|
963
|
-
"fulfillment_item",
|
|
964
|
-
"fulfillment_label",
|
|
965
|
-
"fulfillment_provider",
|
|
966
|
-
"fulfillment_set",
|
|
967
|
-
"geo_zone",
|
|
968
|
-
"image",
|
|
969
|
-
"inventory_count_item",
|
|
970
|
-
"inventory_count_session",
|
|
971
|
-
"inventory_item",
|
|
972
|
-
"inventory_level",
|
|
973
|
-
"inventory_movement",
|
|
974
|
-
"inventory_purchase",
|
|
975
|
-
"inventory_purchase_attachment",
|
|
976
|
-
"inventory_purchase_audit_event",
|
|
977
|
-
"inventory_purchase_batch",
|
|
978
|
-
"inventory_purchase_line_item",
|
|
979
|
-
"invite",
|
|
980
|
-
"invite_rbac_role",
|
|
981
|
-
"invoice",
|
|
982
|
-
"invoice_sequence",
|
|
983
|
-
"layout_configuration",
|
|
984
|
-
"link_module_migrations",
|
|
985
|
-
"location_fulfillment_provider",
|
|
986
|
-
"location_fulfillment_set",
|
|
987
|
-
"loyalty_gift_card",
|
|
988
|
-
"mikro_orm_migrations",
|
|
989
|
-
"notification",
|
|
990
|
-
"notification_provider",
|
|
991
|
-
"notification_tokens",
|
|
992
|
-
"order",
|
|
993
|
-
"order_address",
|
|
994
|
-
"order_cart",
|
|
995
|
-
"order_change",
|
|
996
|
-
"order_change_action",
|
|
997
|
-
"order_claim",
|
|
998
|
-
"order_claim_item",
|
|
999
|
-
"order_claim_item_image",
|
|
1000
|
-
"order_credit_line",
|
|
1001
|
-
"order_exchange",
|
|
1002
|
-
"order_exchange_item",
|
|
1003
|
-
"order_fulfillment",
|
|
1004
|
-
"order_item",
|
|
1005
|
-
"order_line_item",
|
|
1006
|
-
"order_line_item_adjustment",
|
|
1007
|
-
"order_line_item_tax_line",
|
|
1008
|
-
"order_payment_collection",
|
|
1009
|
-
"order_promotion",
|
|
1010
|
-
"order_shipping",
|
|
1011
|
-
"order_shipping_method",
|
|
1012
|
-
"order_shipping_method_adjustment",
|
|
1013
|
-
"order_shipping_method_tax_line",
|
|
1014
|
-
"order_summary",
|
|
1015
|
-
"order_transaction",
|
|
1016
|
-
"otp_verification",
|
|
1017
|
-
"payment",
|
|
1018
|
-
"payment_collection",
|
|
1019
|
-
"payment_collection_payment_providers",
|
|
1020
|
-
"payment_detail",
|
|
1021
|
-
"payment_provider",
|
|
1022
|
-
"payment_session",
|
|
1023
|
-
"payout_request",
|
|
1024
|
-
"price",
|
|
1025
|
-
"price_list",
|
|
1026
|
-
"price_list_rule",
|
|
1027
|
-
"price_preference",
|
|
1028
|
-
"price_rule",
|
|
1029
|
-
"price_set",
|
|
1030
|
-
"product",
|
|
1031
|
-
"product_category",
|
|
1032
|
-
"product_category_product",
|
|
1033
|
-
"product_collection",
|
|
1034
|
-
"product_display_priority",
|
|
1035
|
-
"product_option",
|
|
1036
|
-
"product_option_value",
|
|
1037
|
-
"product_product_option",
|
|
1038
|
-
"product_product_option_value",
|
|
1039
|
-
"product_sales_channel",
|
|
1040
|
-
"product_shipping_profile",
|
|
1041
|
-
"product_tag",
|
|
1042
|
-
"product_tags",
|
|
1043
|
-
"product_type",
|
|
1044
|
-
"product_variant",
|
|
1045
|
-
"product_variant_inventory_item",
|
|
1046
|
-
"product_variant_option",
|
|
1047
|
-
"product_variant_price_set",
|
|
1048
|
-
"product_variant_product_image",
|
|
1049
|
-
"product_view",
|
|
1050
|
-
"promotion",
|
|
1051
|
-
"promotion_application_method",
|
|
1052
|
-
"promotion_campaign",
|
|
1053
|
-
"promotion_campaign_budget",
|
|
1054
|
-
"promotion_campaign_budget_usage",
|
|
1055
|
-
"promotion_promotion_rule",
|
|
1056
|
-
"promotion_rule",
|
|
1057
|
-
"promotion_rule_value",
|
|
1058
|
-
"property_label",
|
|
1059
|
-
"provider_identity",
|
|
1060
|
-
"publishable_api_key_sales_channel",
|
|
1061
|
-
"purchase_supplier",
|
|
1062
|
-
"referral_link",
|
|
1063
|
-
"referral_reward",
|
|
1064
|
-
"refund",
|
|
1065
|
-
"refund_payment_mapping",
|
|
1066
|
-
"refund_reason",
|
|
1067
|
-
"region",
|
|
1068
|
-
"region_country",
|
|
1069
|
-
"region_payment_provider",
|
|
1070
|
-
"reservation_item",
|
|
1071
|
-
"return",
|
|
1072
|
-
"return_fulfillment",
|
|
1073
|
-
"return_item",
|
|
1074
|
-
"return_reason",
|
|
1075
|
-
"review",
|
|
1076
|
-
"sales_channel",
|
|
1077
|
-
"sales_channel_stock_location",
|
|
1078
|
-
"script_migrations",
|
|
1079
|
-
"search_index",
|
|
1080
|
-
"search_index_sync",
|
|
1081
|
-
"search_index_version",
|
|
1082
|
-
"search_postgres_index",
|
|
1083
|
-
"service_zone",
|
|
1084
|
-
"shipment_tracking_event",
|
|
1085
|
-
"shipping_option",
|
|
1086
|
-
"shipping_option_price_set",
|
|
1087
|
-
"shipping_option_rule",
|
|
1088
|
-
"shipping_option_type",
|
|
1089
|
-
"shipping_profile",
|
|
1090
|
-
"skip_merge_cart",
|
|
1091
|
-
"stock_location",
|
|
1092
|
-
"stock_location_address",
|
|
1093
|
-
"store",
|
|
1094
|
-
"store_credit_account",
|
|
1095
|
-
"store_credit_account_transaction",
|
|
1096
|
-
"store_currency",
|
|
1097
|
-
"store_locale",
|
|
1098
|
-
"tax_provider",
|
|
1099
|
-
"tax_rate",
|
|
1100
|
-
"tax_rate_rule",
|
|
1101
|
-
"tax_region",
|
|
1102
|
-
"telegram_config",
|
|
1103
|
-
"telegram_notification_log",
|
|
1104
|
-
"user",
|
|
1105
|
-
"user_preference",
|
|
1106
|
-
"user_rbac_role",
|
|
1107
|
-
"view_configuration",
|
|
1108
|
-
"wallet_account",
|
|
1109
|
-
"wallet_credit_lot",
|
|
1110
|
-
"wallet_gift_card",
|
|
1111
|
-
"wallet_hold",
|
|
1112
|
-
"wallet_ledger_entry",
|
|
1113
|
-
"wallet_rate_limit",
|
|
1114
|
-
"wallet_refund_intent",
|
|
1115
|
-
"wallet_top_up_request",
|
|
1116
|
-
"wishlist",
|
|
1117
|
-
"workflow_execution"
|
|
1118
|
-
];
|
|
1119
|
-
const ENTITY_CATEGORIES = [
|
|
1120
|
-
{ id: "orders", label: "Orders", description: "Orders, items, returns, exchanges and claims" },
|
|
1121
|
-
{ id: "carts", label: "Carts", description: "Shopping carts and checkout data" },
|
|
1122
|
-
{ id: "customers", label: "Customers", description: "Customers, addresses and groups" },
|
|
1123
|
-
{ id: "catalog", label: "Catalog", description: "Products, variants, categories and collections" },
|
|
1124
|
-
{ id: "pricing", label: "Pricing & Promotions", description: "Prices, price lists and promotions" },
|
|
1125
|
-
{ id: "payments", label: "Payments & Refunds", description: "Payments, sessions, captures and refunds" },
|
|
1126
|
-
{ id: "fulfillment", label: "Fulfillment & Shipping", description: "Fulfillments, shipping options and tracking" },
|
|
1127
|
-
{ id: "inventory", label: "Inventory & Purchasing", description: "Stock, locations, reservations and purchases" },
|
|
1128
|
-
{ id: "wallet", label: "Wallet & Credits", description: "Wallets, store credit and gift cards" },
|
|
1129
|
-
{ id: "access", label: "Users & Access", description: "Admin users, logins, roles and API keys" },
|
|
1130
|
-
{ id: "store", label: "Store & Regions", description: "Store, regions, currencies, taxes and sales channels" },
|
|
1131
|
-
{ id: "engagement", label: "Engagement", description: "Reviews, wishlists, referrals and contact requests" },
|
|
1132
|
-
{ id: "notifications", label: "Notifications", description: "Notifications and messaging" },
|
|
1133
|
-
{ id: "system", label: "System & Configuration", description: "Settings, search, workflows and migrations" }
|
|
1134
|
-
];
|
|
1135
|
-
const ENTITY_DEFINITIONS = {
|
|
1136
|
-
// Orders
|
|
1137
|
-
order: { label: "Order", category: "orders" },
|
|
1138
|
-
order_address: { label: "Order Address", category: "orders" },
|
|
1139
|
-
order_cart: { label: "Order–Cart Link", category: "orders" },
|
|
1140
|
-
order_change: { label: "Order Change", category: "orders" },
|
|
1141
|
-
order_change_action: { label: "Order Change Action", category: "orders" },
|
|
1142
|
-
order_claim: { label: "Claim", category: "orders" },
|
|
1143
|
-
order_claim_item: { label: "Claim Item", category: "orders" },
|
|
1144
|
-
order_claim_item_image: { label: "Claim Item Image", category: "orders" },
|
|
1145
|
-
order_credit_line: { label: "Order Credit Line", category: "orders" },
|
|
1146
|
-
order_exchange: { label: "Exchange", category: "orders" },
|
|
1147
|
-
order_exchange_item: { label: "Exchange Item", category: "orders" },
|
|
1148
|
-
order_fulfillment: { label: "Order–Fulfillment Link", category: "orders" },
|
|
1149
|
-
order_item: { label: "Order Item Quantity", category: "orders" },
|
|
1150
|
-
order_line_item: { label: "Order Item", category: "orders" },
|
|
1151
|
-
order_line_item_adjustment: { label: "Order Item Discount", category: "orders" },
|
|
1152
|
-
order_line_item_tax_line: { label: "Order Item Tax", category: "orders" },
|
|
1153
|
-
order_payment_collection: { label: "Order–Payment Link", category: "orders" },
|
|
1154
|
-
order_promotion: { label: "Order Promotion", category: "orders" },
|
|
1155
|
-
order_shipping: { label: "Order Shipping", category: "orders" },
|
|
1156
|
-
order_shipping_method: { label: "Order Shipping Method", category: "orders" },
|
|
1157
|
-
order_shipping_method_adjustment: { label: "Order Shipping Discount", category: "orders" },
|
|
1158
|
-
order_shipping_method_tax_line: { label: "Order Shipping Tax", category: "orders" },
|
|
1159
|
-
order_summary: { label: "Order Summary", category: "orders" },
|
|
1160
|
-
order_transaction: { label: "Order Transaction", category: "orders" },
|
|
1161
|
-
return: { label: "Return", category: "orders" },
|
|
1162
|
-
return_fulfillment: { label: "Return–Fulfillment Link", category: "orders" },
|
|
1163
|
-
return_item: { label: "Return Item", category: "orders" },
|
|
1164
|
-
return_reason: { label: "Return Reason", category: "orders" },
|
|
1165
|
-
cancel_order_reason_mapping: { label: "Order Cancellation Reason", category: "orders" },
|
|
1166
|
-
credit_line: { label: "Credit Line", category: "orders" },
|
|
1167
|
-
invoice: { label: "Invoice", category: "orders" },
|
|
1168
|
-
invoice_sequence: { label: "Invoice Number Sequence", category: "orders" },
|
|
1169
|
-
// Carts
|
|
1170
|
-
cart: { label: "Cart", category: "carts" },
|
|
1171
|
-
cart_address: { label: "Cart Address", category: "carts" },
|
|
1172
|
-
cart_line_item: { label: "Cart Item", category: "carts" },
|
|
1173
|
-
cart_line_item_adjustment: { label: "Cart Item Discount", category: "carts" },
|
|
1174
|
-
cart_line_item_tax_line: { label: "Cart Item Tax", category: "carts" },
|
|
1175
|
-
cart_payment_collection: { label: "Cart–Payment Link", category: "carts" },
|
|
1176
|
-
cart_promotion: { label: "Cart Promotion", category: "carts" },
|
|
1177
|
-
cart_shipping_method: { label: "Cart Shipping Method", category: "carts" },
|
|
1178
|
-
cart_shipping_method_adjustment: { label: "Cart Shipping Discount", category: "carts" },
|
|
1179
|
-
cart_shipping_method_tax_line: { label: "Cart Shipping Tax", category: "carts" },
|
|
1180
|
-
skip_merge_cart: { label: "Cart Merge Exclusion", category: "carts" },
|
|
1181
|
-
// Customers
|
|
1182
|
-
customer: { label: "Customer", category: "customers" },
|
|
1183
|
-
customer_address: { label: "Customer Address", category: "customers" },
|
|
1184
|
-
customer_group: { label: "Customer Group", category: "customers" },
|
|
1185
|
-
customer_group_customer: { label: "Customer Group Member", category: "customers" },
|
|
1186
|
-
customer_account_holder: { label: "Customer–Account Holder Link", category: "customers" },
|
|
1187
|
-
account_holder: { label: "Payment Account Holder", category: "customers" },
|
|
1188
|
-
account_deletion_request: { label: "Account Deletion Request", category: "customers" },
|
|
1189
|
-
payment_detail: { label: "Customer Refund Method", category: "customers" },
|
|
1190
|
-
otp_verification: { label: "OTP Verification", category: "customers" },
|
|
1191
|
-
// Catalog
|
|
1192
|
-
product: { label: "Product", category: "catalog" },
|
|
1193
|
-
product_variant: { label: "Product Variant", category: "catalog" },
|
|
1194
|
-
product_category: { label: "Product Category", category: "catalog" },
|
|
1195
|
-
product_category_product: { label: "Product–Category Link", category: "catalog" },
|
|
1196
|
-
product_collection: { label: "Collection", category: "catalog" },
|
|
1197
|
-
product_option: { label: "Product Option", category: "catalog" },
|
|
1198
|
-
product_option_value: { label: "Product Option Value", category: "catalog" },
|
|
1199
|
-
product_product_option: { label: "Product–Option Link", category: "catalog" },
|
|
1200
|
-
product_product_option_value: { label: "Product–Option Value Link", category: "catalog" },
|
|
1201
|
-
product_tag: { label: "Product Tag", category: "catalog" },
|
|
1202
|
-
product_tags: { label: "Product–Tag Link", category: "catalog" },
|
|
1203
|
-
product_type: { label: "Product Type", category: "catalog" },
|
|
1204
|
-
product_sales_channel: { label: "Product–Sales Channel Link", category: "catalog" },
|
|
1205
|
-
product_shipping_profile: { label: "Product–Shipping Profile Link", category: "catalog" },
|
|
1206
|
-
product_variant_inventory_item: { label: "Variant–Inventory Link", category: "catalog" },
|
|
1207
|
-
product_variant_option: { label: "Variant Option", category: "catalog" },
|
|
1208
|
-
product_variant_price_set: { label: "Variant–Price Link", category: "catalog" },
|
|
1209
|
-
product_variant_product_image: { label: "Variant Image", category: "catalog" },
|
|
1210
|
-
product_display_priority: { label: "Product Display Priority", category: "catalog" },
|
|
1211
|
-
product_view: { label: "Product View", category: "catalog" },
|
|
1212
|
-
image: { label: "Product Image", category: "catalog" },
|
|
1213
|
-
property_label: { label: "Property Label", category: "catalog" },
|
|
1214
|
-
// Pricing & promotions
|
|
1215
|
-
price: { label: "Price", category: "pricing" },
|
|
1216
|
-
price_list: { label: "Price List", category: "pricing" },
|
|
1217
|
-
price_list_rule: { label: "Price List Rule", category: "pricing" },
|
|
1218
|
-
price_preference: { label: "Price Preference", category: "pricing" },
|
|
1219
|
-
price_rule: { label: "Price Rule", category: "pricing" },
|
|
1220
|
-
price_set: { label: "Price Set", category: "pricing" },
|
|
1221
|
-
promotion: { label: "Promotion", category: "pricing" },
|
|
1222
|
-
promotion_application_method: { label: "Promotion Application Method", category: "pricing" },
|
|
1223
|
-
promotion_campaign: { label: "Campaign", category: "pricing" },
|
|
1224
|
-
promotion_campaign_budget: { label: "Campaign Budget", category: "pricing" },
|
|
1225
|
-
promotion_campaign_budget_usage: { label: "Campaign Budget Usage", category: "pricing" },
|
|
1226
|
-
promotion_promotion_rule: { label: "Promotion–Rule Link", category: "pricing" },
|
|
1227
|
-
promotion_rule: { label: "Promotion Rule", category: "pricing" },
|
|
1228
|
-
promotion_rule_value: { label: "Promotion Rule Value", category: "pricing" },
|
|
1229
|
-
application_method_buy_rules: { label: "Promotion Buy Rule", category: "pricing" },
|
|
1230
|
-
application_method_target_rules: { label: "Promotion Target Rule", category: "pricing" },
|
|
1231
|
-
// Payments
|
|
1232
|
-
payment: { label: "Payment", category: "payments" },
|
|
1233
|
-
payment_collection: { label: "Payment Collection", category: "payments" },
|
|
1234
|
-
payment_collection_payment_providers: { label: "Payment Collection–Provider Link", category: "payments" },
|
|
1235
|
-
payment_provider: { label: "Payment Provider", category: "payments" },
|
|
1236
|
-
payment_session: { label: "Payment Session", category: "payments" },
|
|
1237
|
-
capture: { label: "Payment Capture", category: "payments" },
|
|
1238
|
-
refund: { label: "Refund", category: "payments" },
|
|
1239
|
-
refund_reason: { label: "Refund Reason", category: "payments" },
|
|
1240
|
-
refund_payment_mapping: { label: "Return Refund Mapping", category: "payments" },
|
|
1241
|
-
payout_request: { label: "Payout Request", category: "payments" },
|
|
1242
|
-
// Fulfillment
|
|
1243
|
-
fulfillment: { label: "Fulfillment", category: "fulfillment" },
|
|
1244
|
-
fulfillment_address: { label: "Fulfillment Address", category: "fulfillment" },
|
|
1245
|
-
fulfillment_item: { label: "Fulfillment Item", category: "fulfillment" },
|
|
1246
|
-
fulfillment_label: { label: "Shipping Label", category: "fulfillment" },
|
|
1247
|
-
fulfillment_provider: { label: "Fulfillment Provider", category: "fulfillment" },
|
|
1248
|
-
fulfillment_set: { label: "Fulfillment Set", category: "fulfillment" },
|
|
1249
|
-
geo_zone: { label: "Geo Zone", category: "fulfillment" },
|
|
1250
|
-
service_zone: { label: "Service Zone", category: "fulfillment" },
|
|
1251
|
-
shipping_option: { label: "Shipping Option", category: "fulfillment" },
|
|
1252
|
-
shipping_option_price_set: { label: "Shipping Option–Price Link", category: "fulfillment" },
|
|
1253
|
-
shipping_option_rule: { label: "Shipping Option Rule", category: "fulfillment" },
|
|
1254
|
-
shipping_option_type: { label: "Shipping Option Type", category: "fulfillment" },
|
|
1255
|
-
shipping_profile: { label: "Shipping Profile", category: "fulfillment" },
|
|
1256
|
-
shipment_tracking_event: { label: "Shipment Tracking Event", category: "fulfillment" },
|
|
1257
|
-
location_fulfillment_provider: { label: "Location–Fulfillment Provider Link", category: "fulfillment" },
|
|
1258
|
-
location_fulfillment_set: { label: "Location–Fulfillment Set Link", category: "fulfillment" },
|
|
1259
|
-
// Inventory
|
|
1260
|
-
inventory_item: { label: "Inventory Item", category: "inventory" },
|
|
1261
|
-
inventory_level: { label: "Inventory Level", category: "inventory" },
|
|
1262
|
-
inventory_movement: { label: "Inventory Movement", category: "inventory" },
|
|
1263
|
-
inventory_count_item: { label: "Stock Count Item", category: "inventory" },
|
|
1264
|
-
inventory_count_session: { label: "Stock Count Session", category: "inventory" },
|
|
1265
|
-
inventory_purchase: { label: "Purchase", category: "inventory" },
|
|
1266
|
-
inventory_purchase_attachment: { label: "Purchase Attachment", category: "inventory" },
|
|
1267
|
-
inventory_purchase_audit_event: { label: "Purchase Audit Event", category: "inventory" },
|
|
1268
|
-
inventory_purchase_batch: { label: "Purchase Batch", category: "inventory" },
|
|
1269
|
-
inventory_purchase_line_item: { label: "Purchase Item", category: "inventory" },
|
|
1270
|
-
purchase_supplier: { label: "Supplier", category: "inventory" },
|
|
1271
|
-
reservation_item: { label: "Stock Reservation", category: "inventory" },
|
|
1272
|
-
stock_location: { label: "Stock Location", category: "inventory" },
|
|
1273
|
-
stock_location_address: { label: "Stock Location Address", category: "inventory" },
|
|
1274
|
-
sales_channel_stock_location: { label: "Sales Channel–Location Link", category: "inventory" },
|
|
1275
|
-
// Wallet
|
|
1276
|
-
wallet_account: { label: "Wallet Account", category: "wallet" },
|
|
1277
|
-
wallet_credit_lot: { label: "Wallet Credit Lot", category: "wallet" },
|
|
1278
|
-
wallet_gift_card: { label: "Wallet Gift Card", category: "wallet" },
|
|
1279
|
-
wallet_hold: { label: "Wallet Hold", category: "wallet" },
|
|
1280
|
-
wallet_ledger_entry: { label: "Wallet Ledger Entry", category: "wallet" },
|
|
1281
|
-
wallet_rate_limit: { label: "Wallet Rate Limit", category: "wallet" },
|
|
1282
|
-
wallet_refund_intent: { label: "Wallet Refund", category: "wallet" },
|
|
1283
|
-
wallet_top_up_request: { label: "Wallet Top-up Request", category: "wallet" },
|
|
1284
|
-
store_credit_account: { label: "Store Credit Account", category: "wallet" },
|
|
1285
|
-
store_credit_account_transaction: { label: "Store Credit Transaction", category: "wallet" },
|
|
1286
|
-
loyalty_gift_card: { label: "Loyalty Gift Card", category: "wallet" },
|
|
1287
|
-
// Users & access
|
|
1288
|
-
user: { label: "Admin User", category: "access" },
|
|
1289
|
-
user_preference: { label: "User Preference", category: "access" },
|
|
1290
|
-
user_rbac_role: { label: "User Role", category: "access" },
|
|
1291
|
-
invite: { label: "Admin Invite", category: "access" },
|
|
1292
|
-
invite_rbac_role: { label: "Invite Role", category: "access" },
|
|
1293
|
-
api_key: { label: "API Key", category: "access" },
|
|
1294
|
-
publishable_api_key_sales_channel: { label: "API Key–Sales Channel Link", category: "access" },
|
|
1295
|
-
auth_identity: { label: "Login Identity", category: "access" },
|
|
1296
|
-
auth_mfa_factor: { label: "MFA Factor", category: "access" },
|
|
1297
|
-
auth_mfa_recovery_code: { label: "MFA Recovery Code", category: "access" },
|
|
1298
|
-
auth_password_reset_token: { label: "Password Reset Token", category: "access" },
|
|
1299
|
-
auth_verification: { label: "Auth Verification", category: "access" },
|
|
1300
|
-
provider_identity: { label: "Login Provider Identity", category: "access" },
|
|
1301
|
-
// Store & regions
|
|
1302
|
-
store: { label: "Store", category: "store" },
|
|
1303
|
-
store_currency: { label: "Store Currency", category: "store" },
|
|
1304
|
-
store_locale: { label: "Store Locale", category: "store" },
|
|
1305
|
-
currency: { label: "Currency", category: "store" },
|
|
1306
|
-
region: { label: "Region", category: "store" },
|
|
1307
|
-
region_country: { label: "Region Country", category: "store" },
|
|
1308
|
-
region_payment_provider: { label: "Region–Payment Provider Link", category: "store" },
|
|
1309
|
-
sales_channel: { label: "Sales Channel", category: "store" },
|
|
1310
|
-
tax_provider: { label: "Tax Provider", category: "store" },
|
|
1311
|
-
tax_rate: { label: "Tax Rate", category: "store" },
|
|
1312
|
-
tax_rate_rule: { label: "Tax Rate Rule", category: "store" },
|
|
1313
|
-
tax_region: { label: "Tax Region", category: "store" },
|
|
1314
|
-
// Engagement
|
|
1315
|
-
review: { label: "Review", category: "engagement" },
|
|
1316
|
-
wishlist: { label: "Wishlist", category: "engagement" },
|
|
1317
|
-
referral_link: { label: "Referral Link", category: "engagement" },
|
|
1318
|
-
referral_reward: { label: "Referral Reward", category: "engagement" },
|
|
1319
|
-
contact_request: { label: "Contact Request", category: "engagement" },
|
|
1320
|
-
contact_request_comment: { label: "Contact Request Comment", category: "engagement" },
|
|
1321
|
-
contact_email_subscription: { label: "Email Subscription", category: "engagement" },
|
|
1322
|
-
// Notifications
|
|
1323
|
-
notification: { label: "Notification", category: "notifications" },
|
|
1324
|
-
notification_provider: { label: "Notification Provider", category: "notifications" },
|
|
1325
|
-
notification_tokens: { label: "Push Notification Token", category: "notifications" },
|
|
1326
|
-
telegram_config: { label: "Telegram Settings", category: "notifications" },
|
|
1327
|
-
telegram_notification_log: { label: "Telegram Notification Log", category: "notifications" },
|
|
1328
|
-
// System
|
|
1329
|
-
dynamic_config_value: { label: "Plugin Setting", category: "system" },
|
|
1330
|
-
layout_configuration: { label: "Layout Configuration", category: "system" },
|
|
1331
|
-
view_configuration: { label: "View Configuration", category: "system" },
|
|
1332
|
-
workflow_execution: { label: "Workflow Execution", category: "system" },
|
|
1333
|
-
search_index: { label: "Search Index", category: "system" },
|
|
1334
|
-
search_index_sync: { label: "Search Index Sync", category: "system" },
|
|
1335
|
-
search_index_version: { label: "Search Index Version", category: "system" },
|
|
1336
|
-
search_postgres_index: { label: "Search Index Entry", category: "system" },
|
|
1337
|
-
link_module_migrations: { label: "Link Migration Record", category: "system" },
|
|
1338
|
-
mikro_orm_migrations: { label: "Database Migration Record", category: "system" },
|
|
1339
|
-
script_migrations: { label: "Script Migration Record", category: "system" }
|
|
1340
|
-
};
|
|
1341
|
-
const CATEGORY_BY_ID = new Map(ENTITY_CATEGORIES.map((c) => [c.id, c]));
|
|
1342
|
-
const SYSTEM_CATEGORY = CATEGORY_BY_ID.get("system");
|
|
1343
|
-
function humanizeTableName(tableName) {
|
|
1344
|
-
return tableName.split("_").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1345
|
-
}
|
|
1346
|
-
function getEntityInfo(tableName) {
|
|
1347
|
-
const def = ENTITY_DEFINITIONS[tableName];
|
|
1348
|
-
return {
|
|
1349
|
-
tableName,
|
|
1350
|
-
label: def?.label ?? humanizeTableName(tableName),
|
|
1351
|
-
category: def && CATEGORY_BY_ID.get(def.category) || SYSTEM_CATEGORY
|
|
1352
|
-
};
|
|
1353
|
-
}
|
|
1354
|
-
function getEntitiesByCategory() {
|
|
1355
|
-
const groups = /* @__PURE__ */ new Map();
|
|
1356
|
-
for (const table of AUDITED_TABLE_NAMES) {
|
|
1357
|
-
const info = getEntityInfo(table);
|
|
1358
|
-
const list = groups.get(info.category.id) ?? [];
|
|
1359
|
-
list.push(info);
|
|
1360
|
-
groups.set(info.category.id, list);
|
|
1361
|
-
}
|
|
1362
|
-
return ENTITY_CATEGORIES.filter((category) => groups.has(category.id)).map((category) => ({
|
|
1363
|
-
category,
|
|
1364
|
-
entities: (groups.get(category.id) ?? []).sort((a, b) => a.label.localeCompare(b.label))
|
|
1365
|
-
}));
|
|
1366
|
-
}
|
|
1367
|
-
function getCategory(id) {
|
|
1368
|
-
return CATEGORY_BY_ID.get(id);
|
|
1369
|
-
}
|
|
1370
|
-
function getTablesForCategory(id) {
|
|
1371
|
-
return AUDITED_TABLE_NAMES.filter((table) => getEntityInfo(table).category.id === id);
|
|
1372
|
-
}
|
|
1373
|
-
const GROUPS = getEntitiesByCategory();
|
|
1374
|
-
function triggerLabel(entity, category) {
|
|
1375
|
-
if (entity) return getEntityInfo(entity).label;
|
|
1376
|
-
if (category) return `All ${getCategory(category)?.label ?? category}`;
|
|
1377
|
-
return "All entities";
|
|
1378
|
-
}
|
|
1379
|
-
const EntityPicker = ({ entity, category, onChange }) => {
|
|
1380
|
-
const [open, setOpen] = react.useState(false);
|
|
1381
|
-
const [search, setSearch] = react.useState("");
|
|
1382
|
-
const searchRef = react.useRef(null);
|
|
1383
|
-
const filteredGroups = react.useMemo(() => {
|
|
1384
|
-
const term = search.trim().toLowerCase();
|
|
1385
|
-
if (!term) return GROUPS;
|
|
1386
|
-
return GROUPS.map((group) => {
|
|
1387
|
-
const categoryMatches = group.category.label.toLowerCase().includes(term);
|
|
1388
|
-
const entities = categoryMatches ? group.entities : group.entities.filter(
|
|
1389
|
-
(e) => e.label.toLowerCase().includes(term) || e.tableName.includes(term.replace(/\s+/g, "_"))
|
|
1390
|
-
);
|
|
1391
|
-
return { ...group, entities };
|
|
1392
|
-
}).filter((group) => group.entities.length > 0);
|
|
1393
|
-
}, [search]);
|
|
1394
|
-
const select = (next) => {
|
|
1395
|
-
onChange(next);
|
|
1396
|
-
setOpen(false);
|
|
1397
|
-
setSearch("");
|
|
1398
|
-
};
|
|
1399
|
-
const firstMatch = filteredGroups[0]?.entities[0];
|
|
1400
|
-
const isAll = !entity && !category;
|
|
1401
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1402
|
-
ui.Popover,
|
|
1403
|
-
{
|
|
1404
|
-
open,
|
|
1405
|
-
onOpenChange: (next) => {
|
|
1406
|
-
setOpen(next);
|
|
1407
|
-
if (!next) setSearch("");
|
|
1408
|
-
},
|
|
1409
|
-
children: [
|
|
1410
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1411
|
-
"button",
|
|
1412
|
-
{
|
|
1413
|
-
type: "button",
|
|
1414
|
-
"aria-label": "Filter by entity",
|
|
1415
|
-
className: ui.clx(
|
|
1416
|
-
"txt-compact-small flex h-7 w-full min-w-[200px] items-center justify-between gap-2 rounded-md bg-ui-bg-field px-2 text-left shadow-borders-base outline-none transition-fg",
|
|
1417
|
-
"hover:bg-ui-bg-field-hover focus-visible:shadow-borders-interactive-with-active md:w-auto",
|
|
1418
|
-
isAll ? "text-ui-fg-muted" : "text-ui-fg-base"
|
|
1419
|
-
),
|
|
1420
|
-
children: [
|
|
1421
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: triggerLabel(entity, category) }),
|
|
1422
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, { className: "shrink-0 text-ui-fg-muted" })
|
|
1423
|
-
]
|
|
1424
|
-
}
|
|
1425
|
-
) }),
|
|
1426
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1427
|
-
ui.Popover.Content,
|
|
1428
|
-
{
|
|
1429
|
-
align: "start",
|
|
1430
|
-
className: "w-[min(360px,calc(100vw-2rem))] p-0",
|
|
1431
|
-
onOpenAutoFocus: (event) => {
|
|
1432
|
-
event.preventDefault();
|
|
1433
|
-
searchRef.current?.focus();
|
|
1434
|
-
},
|
|
1435
|
-
children: [
|
|
1436
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1437
|
-
ui.Input,
|
|
1438
|
-
{
|
|
1439
|
-
ref: searchRef,
|
|
1440
|
-
size: "small",
|
|
1441
|
-
type: "search",
|
|
1442
|
-
placeholder: "Search entities, e.g. order, wallet…",
|
|
1443
|
-
value: search,
|
|
1444
|
-
onChange: (e) => setSearch(e.target.value),
|
|
1445
|
-
onKeyDown: (e) => {
|
|
1446
|
-
if (e.key === "Enter" && firstMatch) {
|
|
1447
|
-
e.preventDefault();
|
|
1448
|
-
select({ entity: firstMatch.tableName, category: "" });
|
|
1449
|
-
}
|
|
1450
|
-
},
|
|
1451
|
-
"aria-label": "Search entities"
|
|
1452
|
-
}
|
|
1453
|
-
) }),
|
|
1454
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[360px] overflow-y-auto p-1", role: "listbox", "aria-label": "Entities", children: [
|
|
1455
|
-
!search.trim() ? /* @__PURE__ */ jsxRuntime.jsx(PickerOption, { selected: isAll, onSelect: () => select({ entity: "", category: "" }), children: "All entities" }) : null,
|
|
1456
|
-
filteredGroups.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "px-3 py-6 text-center text-ui-fg-muted", children: [
|
|
1457
|
-
"No entities match “",
|
|
1458
|
-
search.trim(),
|
|
1459
|
-
"”"
|
|
1460
|
-
] }) : null,
|
|
1461
|
-
filteredGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1", children: [
|
|
1462
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1 pt-2 text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: group.category.label }),
|
|
1463
|
-
!search.trim() ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1464
|
-
PickerOption,
|
|
1465
|
-
{
|
|
1466
|
-
selected: !entity && category === group.category.id,
|
|
1467
|
-
onSelect: () => select({ entity: "", category: group.category.id }),
|
|
1468
|
-
secondary: group.category.description,
|
|
1469
|
-
children: [
|
|
1470
|
-
"All ",
|
|
1471
|
-
group.category.label
|
|
1472
|
-
]
|
|
1473
|
-
}
|
|
1474
|
-
) : null,
|
|
1475
|
-
group.entities.map((info) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1476
|
-
PickerOption,
|
|
1477
|
-
{
|
|
1478
|
-
selected: entity === info.tableName,
|
|
1479
|
-
onSelect: () => select({ entity: info.tableName, category: "" }),
|
|
1480
|
-
secondary: info.tableName,
|
|
1481
|
-
secondaryMono: true,
|
|
1482
|
-
indent: !search.trim(),
|
|
1483
|
-
children: info.label
|
|
1484
|
-
},
|
|
1485
|
-
info.tableName
|
|
1486
|
-
))
|
|
1487
|
-
] }, group.category.id))
|
|
1488
|
-
] })
|
|
1489
|
-
]
|
|
1490
|
-
}
|
|
1491
|
-
)
|
|
1492
|
-
]
|
|
1493
|
-
}
|
|
1494
|
-
);
|
|
1495
|
-
};
|
|
1496
|
-
const PickerOption = ({ selected, onSelect, children, secondary, secondaryMono, indent }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1497
|
-
"button",
|
|
1498
|
-
{
|
|
1499
|
-
type: "button",
|
|
1500
|
-
role: "option",
|
|
1501
|
-
"aria-selected": selected,
|
|
1502
|
-
onClick: onSelect,
|
|
1503
|
-
className: ui.clx(
|
|
1504
|
-
"flex w-full items-start gap-2 rounded-md px-2 py-1.5 text-left outline-none transition-fg",
|
|
1505
|
-
"hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-hover",
|
|
1506
|
-
indent && "pl-4"
|
|
1507
|
-
),
|
|
1508
|
-
children: [
|
|
1509
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 flex size-4 shrink-0 items-center justify-center text-ui-fg-interactive", children: selected ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : null }),
|
|
1510
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
1511
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm text-ui-fg-base", children }),
|
|
1512
|
-
secondary ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("truncate text-xs text-ui-fg-muted", secondaryMono && "font-mono"), children: secondary }) : null
|
|
1513
|
-
] })
|
|
1514
|
-
]
|
|
1515
|
-
}
|
|
1516
|
-
);
|
|
1517
|
-
const CopyableId = ({ value, emptyLabel = "No ID", className }) => {
|
|
1518
|
-
if (!value) {
|
|
1519
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "italic text-ui-fg-muted", children: emptyLabel });
|
|
1520
|
-
}
|
|
1521
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("inline-flex min-w-0 max-w-full items-center gap-1", className), children: [
|
|
1522
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-xs text-ui-fg-base", title: value, children: value }),
|
|
1523
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { onClick: (e) => e.stopPropagation(), className: "inline-flex shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Copy, { content: value, variant: "mini", className: "text-ui-fg-muted", "aria-label": `Copy ${value}` }) })
|
|
1524
|
-
] });
|
|
1525
|
-
};
|
|
1526
|
-
const RELATIVE_UNITS = [
|
|
1527
|
-
{ unit: "year", seconds: 60 * 60 * 24 * 365 },
|
|
1528
|
-
{ unit: "month", seconds: 60 * 60 * 24 * 30 },
|
|
1529
|
-
{ unit: "week", seconds: 60 * 60 * 24 * 7 },
|
|
1530
|
-
{ unit: "day", seconds: 60 * 60 * 24 },
|
|
1531
|
-
{ unit: "hour", seconds: 60 * 60 },
|
|
1532
|
-
{ unit: "minute", seconds: 60 }
|
|
1533
|
-
];
|
|
1534
|
-
function toDate(value) {
|
|
1535
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
1536
|
-
return Number.isNaN(date.getTime()) ? null : date;
|
|
1537
|
-
}
|
|
1538
|
-
function formatRelativeTime(value, now = /* @__PURE__ */ new Date()) {
|
|
1539
|
-
const date = toDate(value);
|
|
1540
|
-
if (!date) return "—";
|
|
1541
|
-
const diffSeconds = Math.round((date.getTime() - now.getTime()) / 1e3);
|
|
1542
|
-
if (Math.abs(diffSeconds) < 45) return "just now";
|
|
1543
|
-
const rtf = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
|
|
1544
|
-
for (const { unit, seconds } of RELATIVE_UNITS) {
|
|
1545
|
-
if (Math.abs(diffSeconds) >= seconds) {
|
|
1546
|
-
return rtf.format(Math.round(diffSeconds / seconds), unit);
|
|
1547
|
-
}
|
|
1548
|
-
}
|
|
1549
|
-
return rtf.format(Math.round(diffSeconds / 60), "minute");
|
|
1550
|
-
}
|
|
1551
|
-
function formatExactDateTime(value) {
|
|
1552
|
-
const date = toDate(value);
|
|
1553
|
-
if (!date) return "—";
|
|
1554
|
-
return new Intl.DateTimeFormat(void 0, {
|
|
1555
|
-
day: "2-digit",
|
|
1556
|
-
month: "short",
|
|
1557
|
-
year: "numeric",
|
|
1558
|
-
hour: "2-digit",
|
|
1559
|
-
minute: "2-digit",
|
|
1560
|
-
second: "2-digit",
|
|
1561
|
-
timeZoneName: "short"
|
|
1562
|
-
}).format(date);
|
|
1563
|
-
}
|
|
1564
|
-
function formatDate(value) {
|
|
1565
|
-
const date = toDate(value);
|
|
1566
|
-
if (!date) return "—";
|
|
1567
|
-
return new Intl.DateTimeFormat(void 0, { day: "2-digit", month: "short", year: "numeric" }).format(date);
|
|
1568
|
-
}
|
|
1569
|
-
function formatNumber(value) {
|
|
1570
|
-
return new Intl.NumberFormat().format(value);
|
|
1571
|
-
}
|
|
1572
|
-
function formatMoney(amount, currencyCode) {
|
|
1573
|
-
const code = currencyCode?.trim().toUpperCase();
|
|
1574
|
-
if (code && /^[A-Z]{3}$/.test(code)) {
|
|
1575
|
-
try {
|
|
1576
|
-
return new Intl.NumberFormat(void 0, { style: "currency", currency: code }).format(amount);
|
|
1577
|
-
} catch {
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
return code ? `${code} ${formatNumber(amount)}` : formatNumber(amount);
|
|
1581
|
-
}
|
|
1582
|
-
const SOURCE_ALIASES = {
|
|
1583
|
-
admin: { kind: "admin", label: "Admin Panel" },
|
|
1584
|
-
admin_panel: { kind: "admin", label: "Admin Panel" },
|
|
1585
|
-
dashboard: { kind: "admin", label: "Admin Panel" },
|
|
1586
|
-
api: { kind: "api", label: "API" },
|
|
1587
|
-
store_api: { kind: "api", label: "Storefront API" },
|
|
1588
|
-
admin_api: { kind: "api", label: "Admin API" },
|
|
1589
|
-
system: { kind: "system", label: "System" },
|
|
1590
|
-
job: { kind: "job", label: "Background Job" },
|
|
1591
|
-
background_job: { kind: "job", label: "Background Job" },
|
|
1592
|
-
scheduled_job: { kind: "job", label: "Background Job" },
|
|
1593
|
-
cron: { kind: "job", label: "Background Job" },
|
|
1594
|
-
workflow: { kind: "workflow", label: "Workflow" },
|
|
1595
|
-
migration: { kind: "system", label: "Migration" }
|
|
1596
|
-
};
|
|
1597
|
-
function describeSource(source) {
|
|
1598
|
-
if (!source || !source.trim()) return { kind: "unknown", label: "Unknown" };
|
|
1599
|
-
const key = source.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
1600
|
-
return SOURCE_ALIASES[key] ?? { kind: "other", label: source.trim() };
|
|
1601
|
-
}
|
|
1602
|
-
function sourceBadgeColor(kind) {
|
|
1603
|
-
switch (kind) {
|
|
1604
|
-
case "admin":
|
|
1605
|
-
return "blue";
|
|
1606
|
-
case "api":
|
|
1607
|
-
return "purple";
|
|
1608
|
-
case "job":
|
|
1609
|
-
case "workflow":
|
|
1610
|
-
return "orange";
|
|
1611
|
-
case "system":
|
|
1612
|
-
return "green";
|
|
1613
|
-
default:
|
|
1614
|
-
return "grey";
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
const CARDS = [
|
|
1618
|
-
{ key: "total", label: "Total deleted", hint: "All records captured since auditing began" },
|
|
1619
|
-
{ key: "today", label: "Today", hint: "Deleted since midnight (your time)" },
|
|
1620
|
-
{ key: "last_7_days", label: "Last 7 days", hint: "Including today" },
|
|
1621
|
-
{ key: "tables_affected", label: "Entity types affected", hint: "Distinct kinds of records deleted" }
|
|
1622
|
-
];
|
|
1623
|
-
const SummaryCards = ({ stats, loading, failed }) => {
|
|
1624
|
-
if (failed && !stats) return null;
|
|
1625
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: CARDS.map((card) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1626
|
-
"div",
|
|
1627
|
-
{
|
|
1628
|
-
className: "flex flex-col gap-1 rounded-lg border border-ui-border-base bg-ui-bg-subtle px-4 py-3",
|
|
1629
|
-
title: card.hint,
|
|
1630
|
-
children: [
|
|
1631
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: card.label }),
|
|
1632
|
-
loading || !stats ? /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-16" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-2xl font-semibold leading-8 text-ui-fg-base", children: formatNumber(stats[card.key]) })
|
|
1633
|
-
]
|
|
1634
|
-
},
|
|
1635
|
-
card.key
|
|
1636
|
-
)) });
|
|
1637
|
-
};
|
|
1638
|
-
const BASE = "/admin/deleted-records-audit";
|
|
1639
|
-
class AuditApiError extends Error {
|
|
1640
|
-
status;
|
|
1641
|
-
constructor(message, status) {
|
|
1642
|
-
super(message);
|
|
1643
|
-
this.status = status;
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
async function getJson(url, signal) {
|
|
1647
|
-
const response = await fetch(url, { credentials: "include", signal });
|
|
1648
|
-
if (!response.ok) {
|
|
1649
|
-
let message = response.statusText || "Request failed";
|
|
1650
|
-
try {
|
|
1651
|
-
const body = await response.json();
|
|
1652
|
-
if (body && typeof body === "object" && "message" in body && typeof body.message === "string") {
|
|
1653
|
-
message = body.message;
|
|
1654
|
-
}
|
|
1655
|
-
} catch {
|
|
1656
|
-
}
|
|
1657
|
-
throw new AuditApiError(message, response.status);
|
|
1658
|
-
}
|
|
1659
|
-
return await response.json();
|
|
1660
|
-
}
|
|
1661
|
-
function fetchAuditList(params, signal) {
|
|
1662
|
-
return getJson(`${BASE}?${params.toString()}`, signal);
|
|
1663
|
-
}
|
|
1664
|
-
async function fetchAuditStats(signal) {
|
|
1665
|
-
const todayStart = /* @__PURE__ */ new Date();
|
|
1666
|
-
todayStart.setHours(0, 0, 0, 0);
|
|
1667
|
-
const params = new URLSearchParams({ today_start: todayStart.toISOString() });
|
|
1668
|
-
const body = await getJson(`${BASE}/stats?${params.toString()}`, signal);
|
|
1669
|
-
return body.stats;
|
|
1670
|
-
}
|
|
1671
|
-
async function fetchAuditDetail(id, signal) {
|
|
1672
|
-
const body = await getJson(`${BASE}/${encodeURIComponent(id)}`, signal);
|
|
1673
|
-
return body.audit;
|
|
1674
|
-
}
|
|
1675
|
-
const LAST_LIST_URL_KEY = "om.deleted-records-audit.last-list-search";
|
|
1676
|
-
const DATE_PRESETS = [
|
|
1677
|
-
{ value: "any", label: "Any time" },
|
|
1678
|
-
{ value: "today", label: "Today" },
|
|
1679
|
-
{ value: "yesterday", label: "Yesterday" },
|
|
1680
|
-
{ value: "7d", label: "Last 7 days" },
|
|
1681
|
-
{ value: "30d", label: "Last 30 days" },
|
|
1682
|
-
{ value: "custom", label: "Custom range" }
|
|
1683
|
-
];
|
|
1684
|
-
const EMPTY_FILTERS = {
|
|
1685
|
-
q: "",
|
|
1686
|
-
entity: "",
|
|
1687
|
-
category: "",
|
|
1688
|
-
date: "any",
|
|
1689
|
-
from: "",
|
|
1690
|
-
to: "",
|
|
1691
|
-
source: "",
|
|
1692
|
-
deletedBy: ""
|
|
1693
|
-
};
|
|
1694
|
-
const URL_KEYS = {
|
|
1695
|
-
q: "q",
|
|
1696
|
-
entity: "entity",
|
|
1697
|
-
category: "category",
|
|
1698
|
-
date: "date",
|
|
1699
|
-
from: "from",
|
|
1700
|
-
to: "to",
|
|
1701
|
-
source: "source",
|
|
1702
|
-
deletedBy: "deleted_by"
|
|
1703
|
-
};
|
|
1704
|
-
const DATE_PRESET_VALUES = new Set(DATE_PRESETS.map((p) => p.value));
|
|
1705
|
-
const DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
1706
|
-
function filtersFromSearchParams(params) {
|
|
1707
|
-
const read = (key) => params.get(URL_KEYS[key])?.trim() ?? "";
|
|
1708
|
-
const date = read("date");
|
|
1709
|
-
const from = read("from");
|
|
1710
|
-
const to = read("to");
|
|
1711
|
-
return {
|
|
1712
|
-
q: read("q"),
|
|
1713
|
-
entity: read("entity"),
|
|
1714
|
-
category: read("category"),
|
|
1715
|
-
date: DATE_PRESET_VALUES.has(date) ? date : "any",
|
|
1716
|
-
from: DAY_PATTERN.test(from) ? from : "",
|
|
1717
|
-
to: DAY_PATTERN.test(to) ? to : "",
|
|
1718
|
-
source: read("source"),
|
|
1719
|
-
deletedBy: read("deletedBy")
|
|
1720
|
-
};
|
|
1721
|
-
}
|
|
1722
|
-
function filtersToSearchParams(filters) {
|
|
1723
|
-
const params = new URLSearchParams();
|
|
1724
|
-
for (const key of Object.keys(URL_KEYS)) {
|
|
1725
|
-
const value = filters[key];
|
|
1726
|
-
if (!value || value === EMPTY_FILTERS[key]) continue;
|
|
1727
|
-
if ((key === "from" || key === "to") && filters.date !== "custom") continue;
|
|
1728
|
-
params.set(URL_KEYS[key], value);
|
|
1729
|
-
}
|
|
1730
|
-
return params;
|
|
1731
|
-
}
|
|
1732
|
-
function hasActiveFilters(filters) {
|
|
1733
|
-
return filtersToSearchParams(filters).toString() !== "";
|
|
1734
|
-
}
|
|
1735
|
-
function startOfDay(date) {
|
|
1736
|
-
const d = new Date(date);
|
|
1737
|
-
d.setHours(0, 0, 0, 0);
|
|
1738
|
-
return d;
|
|
1739
|
-
}
|
|
1740
|
-
function endOfDay(date) {
|
|
1741
|
-
const d = new Date(date);
|
|
1742
|
-
d.setHours(23, 59, 59, 999);
|
|
1743
|
-
return d;
|
|
1744
|
-
}
|
|
1745
|
-
function parseDay(day) {
|
|
1746
|
-
if (!DAY_PATTERN.test(day)) return null;
|
|
1747
|
-
const [y, m, d] = day.split("-").map(Number);
|
|
1748
|
-
const date = new Date(y, m - 1, d);
|
|
1749
|
-
return Number.isNaN(date.getTime()) ? null : date;
|
|
1750
|
-
}
|
|
1751
|
-
function resolveDateRange(filters, now = /* @__PURE__ */ new Date()) {
|
|
1752
|
-
const today = startOfDay(now);
|
|
1753
|
-
switch (filters.date) {
|
|
1754
|
-
case "today":
|
|
1755
|
-
return { from: today };
|
|
1756
|
-
case "yesterday": {
|
|
1757
|
-
const y = new Date(today);
|
|
1758
|
-
y.setDate(y.getDate() - 1);
|
|
1759
|
-
return { from: y, to: endOfDay(y) };
|
|
1760
|
-
}
|
|
1761
|
-
case "7d": {
|
|
1762
|
-
const from = new Date(today);
|
|
1763
|
-
from.setDate(from.getDate() - 6);
|
|
1764
|
-
return { from };
|
|
1765
|
-
}
|
|
1766
|
-
case "30d": {
|
|
1767
|
-
const from = new Date(today);
|
|
1768
|
-
from.setDate(from.getDate() - 29);
|
|
1769
|
-
return { from };
|
|
1770
|
-
}
|
|
1771
|
-
case "custom": {
|
|
1772
|
-
const from = parseDay(filters.from);
|
|
1773
|
-
const to = parseDay(filters.to);
|
|
1774
|
-
return { from: from ?? void 0, to: to ? endOfDay(to) : void 0 };
|
|
1775
|
-
}
|
|
1776
|
-
default:
|
|
1777
|
-
return {};
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1780
|
-
function filtersToApiParams(filters, page, now = /* @__PURE__ */ new Date()) {
|
|
1781
|
-
const params = new URLSearchParams();
|
|
1782
|
-
params.set("limit", String(page.limit));
|
|
1783
|
-
params.set("offset", String(page.offset));
|
|
1784
|
-
if (filters.q) params.set("q", filters.q);
|
|
1785
|
-
if (filters.entity) {
|
|
1786
|
-
params.set("table_name", filters.entity);
|
|
1787
|
-
} else if (filters.category) {
|
|
1788
|
-
const tables = getTablesForCategory(filters.category);
|
|
1789
|
-
if (tables.length) params.set("table_names", tables.join(","));
|
|
1790
|
-
}
|
|
1791
|
-
const range = resolveDateRange(filters, now);
|
|
1792
|
-
if (range.from) params.set("date_from", range.from.toISOString());
|
|
1793
|
-
if (range.to) params.set("date_to", range.to.toISOString());
|
|
1794
|
-
if (filters.source) params.set("source", filters.source);
|
|
1795
|
-
if (filters.deletedBy) params.set("deleted_by", filters.deletedBy);
|
|
1796
|
-
return params;
|
|
1797
|
-
}
|
|
1798
|
-
const PAGE_SIZE = 50;
|
|
1799
|
-
const RESTORE_PAGE_SIZE = 100;
|
|
1800
|
-
const MAX_RESTORE_ROWS = 500;
|
|
1801
|
-
const ALL = "__all__";
|
|
1802
|
-
const UNKNOWN_SOURCE = "unknown";
|
|
1803
|
-
const LOADED_COUNT_KEY_PREFIX = "om.deleted-records-audit.loaded:";
|
|
1804
|
-
const LAST_VIEWED_KEY = "om.deleted-records-audit.last-viewed";
|
|
1805
|
-
function readSession(key) {
|
|
1806
|
-
try {
|
|
1807
|
-
return window.sessionStorage.getItem(key);
|
|
1808
|
-
} catch {
|
|
1809
|
-
return null;
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
function writeSession(key, value) {
|
|
1813
|
-
try {
|
|
1814
|
-
window.sessionStorage.setItem(key, value);
|
|
1815
|
-
} catch {
|
|
1816
|
-
}
|
|
1817
|
-
}
|
|
1818
|
-
const DeletedRecordsPage = () => {
|
|
1819
|
-
const navigate = reactRouterDom.useNavigate();
|
|
1820
|
-
const location = reactRouterDom.useLocation();
|
|
1821
|
-
const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
|
|
1822
|
-
const filters = react.useMemo(() => filtersFromSearchParams(searchParams), [searchParams]);
|
|
1823
|
-
const filterKey = filtersToSearchParams(filters).toString();
|
|
1824
|
-
const filtersActive = hasActiveFilters(filters);
|
|
1825
|
-
const [searchText, setSearchText] = react.useState(filters.q);
|
|
1826
|
-
const [items, setItems] = react.useState([]);
|
|
1827
|
-
const [count, setCount] = react.useState(0);
|
|
1828
|
-
const [isLoading, setIsLoading] = react.useState(true);
|
|
1829
|
-
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1830
|
-
const [error, setError] = react.useState(null);
|
|
1831
|
-
const [stats, setStats] = react.useState(null);
|
|
1832
|
-
const [statsLoading, setStatsLoading] = react.useState(true);
|
|
1833
|
-
const [statsFailed, setStatsFailed] = react.useState(false);
|
|
1834
|
-
const [reloadToken, setReloadToken] = react.useState(0);
|
|
1835
|
-
const [highlightId, setHighlightId] = react.useState(null);
|
|
1836
|
-
const restoredScrollRef = react.useRef(false);
|
|
1837
|
-
const updateFilters = react.useCallback(
|
|
1838
|
-
(patch) => {
|
|
1839
|
-
const next = { ...filters, ...patch };
|
|
1840
|
-
setSearchParams(filtersToSearchParams(next), { replace: true });
|
|
1841
|
-
},
|
|
1842
|
-
[filters, setSearchParams]
|
|
1843
|
-
);
|
|
1844
|
-
react.useEffect(() => {
|
|
1845
|
-
if (searchText.trim() === filters.q) return;
|
|
1846
|
-
const handle = setTimeout(() => updateFilters({ q: searchText.trim() }), 300);
|
|
1847
|
-
return () => clearTimeout(handle);
|
|
1848
|
-
}, [searchText, filters.q, updateFilters]);
|
|
1849
|
-
react.useEffect(() => {
|
|
1850
|
-
setSearchText((current) => current.trim() === filters.q ? current : filters.q);
|
|
1851
|
-
}, [filters.q]);
|
|
1852
|
-
react.useEffect(() => {
|
|
1853
|
-
writeSession(LAST_LIST_URL_KEY, location.search);
|
|
1854
|
-
}, [location.search]);
|
|
1855
|
-
const loadStats = react.useCallback(async (signal) => {
|
|
1856
|
-
setStatsLoading(true);
|
|
1857
|
-
setStatsFailed(false);
|
|
1858
|
-
try {
|
|
1859
|
-
setStats(await fetchAuditStats(signal));
|
|
1860
|
-
} catch (e) {
|
|
1861
|
-
if (!signal?.aborted) setStatsFailed(true);
|
|
1862
|
-
} finally {
|
|
1863
|
-
if (!signal?.aborted) setStatsLoading(false);
|
|
1864
|
-
}
|
|
1865
|
-
}, []);
|
|
1866
|
-
react.useEffect(() => {
|
|
1867
|
-
const controller = new AbortController();
|
|
1868
|
-
void loadStats(controller.signal);
|
|
1869
|
-
return () => controller.abort();
|
|
1870
|
-
}, [loadStats, reloadToken]);
|
|
1871
|
-
react.useEffect(() => {
|
|
1872
|
-
const controller = new AbortController();
|
|
1873
|
-
const restoreTarget = Math.min(
|
|
1874
|
-
MAX_RESTORE_ROWS,
|
|
1875
|
-
Math.max(PAGE_SIZE, Number(readSession(LOADED_COUNT_KEY_PREFIX + filterKey)) || 0)
|
|
1876
|
-
);
|
|
1877
|
-
setIsLoading(true);
|
|
1878
|
-
setError(null);
|
|
1879
|
-
(async () => {
|
|
1880
|
-
try {
|
|
1881
|
-
const collected = [];
|
|
1882
|
-
let total = 0;
|
|
1883
|
-
while (collected.length < restoreTarget) {
|
|
1884
|
-
const limit = restoreTarget > PAGE_SIZE ? RESTORE_PAGE_SIZE : PAGE_SIZE;
|
|
1885
|
-
const page = await fetchAuditList(
|
|
1886
|
-
filtersToApiParams(filters, { limit, offset: collected.length }),
|
|
1887
|
-
controller.signal
|
|
1888
|
-
);
|
|
1889
|
-
total = page.count;
|
|
1890
|
-
collected.push(...page.audits);
|
|
1891
|
-
if (page.audits.length < limit || collected.length >= total) break;
|
|
1892
|
-
}
|
|
1893
|
-
if (controller.signal.aborted) return;
|
|
1894
|
-
setItems(collected.slice(0, restoreTarget));
|
|
1895
|
-
setCount(total);
|
|
1896
|
-
} catch (e) {
|
|
1897
|
-
if (controller.signal.aborted) return;
|
|
1898
|
-
setItems([]);
|
|
1899
|
-
setCount(0);
|
|
1900
|
-
setError(e instanceof Error ? e.message : "Unknown error");
|
|
1901
|
-
} finally {
|
|
1902
|
-
if (!controller.signal.aborted) setIsLoading(false);
|
|
1903
|
-
}
|
|
1904
|
-
})();
|
|
1905
|
-
return () => controller.abort();
|
|
1906
|
-
}, [filterKey, reloadToken]);
|
|
1907
|
-
react.useEffect(() => {
|
|
1908
|
-
if (!isLoading) writeSession(LOADED_COUNT_KEY_PREFIX + filterKey, String(items.length));
|
|
1909
|
-
}, [items.length, isLoading, filterKey]);
|
|
1910
|
-
react.useEffect(() => {
|
|
1911
|
-
if (isLoading || restoredScrollRef.current) return;
|
|
1912
|
-
restoredScrollRef.current = true;
|
|
1913
|
-
const lastViewed = readSession(LAST_VIEWED_KEY);
|
|
1914
|
-
if (!lastViewed || !items.some((item) => item.id === lastViewed)) return;
|
|
1915
|
-
setHighlightId(lastViewed);
|
|
1916
|
-
requestAnimationFrame(() => {
|
|
1917
|
-
const visible = Array.from(document.querySelectorAll(`[data-audit-row="${lastViewed}"]`)).find(
|
|
1918
|
-
(el) => el.offsetParent !== null
|
|
1919
|
-
);
|
|
1920
|
-
visible?.scrollIntoView({ block: "center" });
|
|
1921
|
-
});
|
|
1922
|
-
const handle = setTimeout(() => setHighlightId(null), 2500);
|
|
1923
|
-
return () => clearTimeout(handle);
|
|
1924
|
-
}, [isLoading, items]);
|
|
1925
|
-
const loadMore = async () => {
|
|
1926
|
-
setIsFetchingMore(true);
|
|
1927
|
-
try {
|
|
1928
|
-
const page = await fetchAuditList(filtersToApiParams(filters, { limit: PAGE_SIZE, offset: items.length }));
|
|
1929
|
-
setItems((prev) => [...prev, ...page.audits]);
|
|
1930
|
-
setCount(page.count);
|
|
1931
|
-
} catch (e) {
|
|
1932
|
-
setError(e instanceof Error ? e.message : "Unknown error");
|
|
1933
|
-
} finally {
|
|
1934
|
-
setIsFetchingMore(false);
|
|
1935
|
-
}
|
|
1936
|
-
};
|
|
1937
|
-
const openDetail = (id) => {
|
|
1938
|
-
writeSession(LAST_VIEWED_KEY, id);
|
|
1939
|
-
navigate(`/deleted-records-audit/${id}`, { state: { fromList: true } });
|
|
1940
|
-
};
|
|
1941
|
-
const clearFilters = () => {
|
|
1942
|
-
setSearchText("");
|
|
1943
|
-
setSearchParams(filtersToSearchParams(EMPTY_FILTERS), { replace: true });
|
|
1944
|
-
};
|
|
1945
|
-
const refresh = () => setReloadToken((t) => t + 1);
|
|
1946
|
-
const hasMore = items.length < count;
|
|
1947
|
-
const knownSources = stats?.sources ?? [];
|
|
1948
|
-
const knownDeletedBy = stats?.deleted_by ?? [];
|
|
1949
|
-
const attributionMissing = !!stats && stats.total > 0 && knownSources.length === 0 && knownDeletedBy.length === 0;
|
|
1950
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-3 md:p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-4 md:p-6", children: [
|
|
1951
|
-
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-start md:justify-between", children: [
|
|
1952
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1953
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Deleted Records" }),
|
|
1954
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Review records that were permanently deleted from the system." })
|
|
1955
|
-
] }),
|
|
1956
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: refresh, isLoading: isLoading && items.length > 0, children: [
|
|
1957
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
1958
|
-
"Refresh"
|
|
1959
|
-
] })
|
|
1960
|
-
] }),
|
|
1961
|
-
/* @__PURE__ */ jsxRuntime.jsx(SummaryCards, { stats, loading: statsLoading, failed: statsFailed }),
|
|
1962
|
-
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-3", "aria-label": "Search and filters", children: [
|
|
1963
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1964
|
-
ui.Input,
|
|
1965
|
-
{
|
|
1966
|
-
type: "search",
|
|
1967
|
-
size: "base",
|
|
1968
|
-
placeholder: "Search by record ID, e.g. order_01J…, prod_…, cus_…",
|
|
1969
|
-
value: searchText,
|
|
1970
|
-
onChange: (e) => setSearchText(e.target.value),
|
|
1971
|
-
"aria-label": "Search by record ID",
|
|
1972
|
-
className: "w-full"
|
|
1973
|
-
}
|
|
1974
|
-
),
|
|
1975
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 md:flex-row md:flex-wrap md:items-center", children: [
|
|
1976
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1977
|
-
EntityPicker,
|
|
1978
|
-
{
|
|
1979
|
-
entity: filters.entity,
|
|
1980
|
-
category: filters.category,
|
|
1981
|
-
onChange: (next) => updateFilters(next)
|
|
1982
|
-
}
|
|
1983
|
-
),
|
|
1984
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:w-[160px]", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1985
|
-
ui.Select,
|
|
1986
|
-
{
|
|
1987
|
-
size: "small",
|
|
1988
|
-
value: filters.date,
|
|
1989
|
-
onValueChange: (value) => updateFilters({ date: value }),
|
|
1990
|
-
children: [
|
|
1991
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { "aria-label": "Filter by date", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
1992
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: DATE_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: preset.value, children: preset.label }, preset.value)) })
|
|
1993
|
-
]
|
|
1994
|
-
}
|
|
1995
|
-
) }),
|
|
1996
|
-
filters.date === "custom" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1997
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1998
|
-
ui.Input,
|
|
1999
|
-
{
|
|
2000
|
-
type: "date",
|
|
2001
|
-
size: "small",
|
|
2002
|
-
value: filters.from,
|
|
2003
|
-
max: filters.to || void 0,
|
|
2004
|
-
onChange: (e) => updateFilters({ from: e.target.value }),
|
|
2005
|
-
"aria-label": "From date"
|
|
2006
|
-
}
|
|
2007
|
-
),
|
|
2008
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "to" }),
|
|
2009
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2010
|
-
ui.Input,
|
|
2011
|
-
{
|
|
2012
|
-
type: "date",
|
|
2013
|
-
size: "small",
|
|
2014
|
-
value: filters.to,
|
|
2015
|
-
min: filters.from || void 0,
|
|
2016
|
-
onChange: (e) => updateFilters({ to: e.target.value }),
|
|
2017
|
-
"aria-label": "To date"
|
|
2018
|
-
}
|
|
2019
|
-
)
|
|
2020
|
-
] }) : null,
|
|
2021
|
-
knownSources.length > 0 || filters.source ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:w-[170px]", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2022
|
-
ui.Select,
|
|
2023
|
-
{
|
|
2024
|
-
size: "small",
|
|
2025
|
-
value: filters.source || ALL,
|
|
2026
|
-
onValueChange: (value) => updateFilters({ source: value === ALL ? "" : value }),
|
|
2027
|
-
children: [
|
|
2028
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { "aria-label": "Filter by source", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
2029
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
2030
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: ALL, children: "All sources" }),
|
|
2031
|
-
knownSources.map((source) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: source, children: describeSource(source).label }, source)),
|
|
2032
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: UNKNOWN_SOURCE, children: "Unknown" })
|
|
2033
|
-
] })
|
|
2034
|
-
]
|
|
2035
|
-
}
|
|
2036
|
-
) }) : null,
|
|
2037
|
-
knownDeletedBy.length > 0 || filters.deletedBy ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:w-[200px]", children: [
|
|
2038
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2039
|
-
ui.Input,
|
|
2040
|
-
{
|
|
2041
|
-
size: "small",
|
|
2042
|
-
list: "deleted-records-audit-deleted-by",
|
|
2043
|
-
placeholder: "Deleted by (all users)",
|
|
2044
|
-
defaultValue: filters.deletedBy,
|
|
2045
|
-
onBlur: (e) => updateFilters({ deletedBy: e.target.value.trim() }),
|
|
2046
|
-
onKeyDown: (e) => {
|
|
2047
|
-
if (e.key === "Enter") updateFilters({ deletedBy: e.currentTarget.value.trim() });
|
|
2048
|
-
},
|
|
2049
|
-
"aria-label": "Filter by who deleted the record"
|
|
2050
|
-
},
|
|
2051
|
-
filters.deletedBy
|
|
2052
|
-
),
|
|
2053
|
-
/* @__PURE__ */ jsxRuntime.jsx("datalist", { id: "deleted-records-audit-deleted-by", children: knownDeletedBy.map((value) => /* @__PURE__ */ jsxRuntime.jsx("option", { value }, value)) })
|
|
2054
|
-
] }) : null,
|
|
2055
|
-
filtersActive ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: clearFilters, children: "Clear filters" }) : null
|
|
2056
|
-
] })
|
|
2057
|
-
] }),
|
|
2058
|
-
attributionMissing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: [
|
|
2059
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.InformationCircle, { className: "mt-0.5 shrink-0 text-ui-fg-muted" }),
|
|
2060
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Who deleted a record and where the deletion came from are not being recorded yet, so those columns show “Unknown”. Every deleted record is still captured in full." })
|
|
2061
|
-
] }) : null,
|
|
2062
|
-
!isLoading && !error && items.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", "aria-live": "polite", children: [
|
|
2063
|
-
"Showing ",
|
|
2064
|
-
formatNumber(items.length),
|
|
2065
|
-
" of ",
|
|
2066
|
-
formatNumber(count),
|
|
2067
|
-
" ",
|
|
2068
|
-
count === 1 ? "record" : "records",
|
|
2069
|
-
filtersActive ? " matching your filters" : ""
|
|
2070
|
-
] }) : null,
|
|
2071
|
-
error ? /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { onRetry: refresh, detail: error }) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ListSkeleton, {}) : items.length === 0 ? filtersActive ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2072
|
-
EmptyState,
|
|
2073
|
-
{
|
|
2074
|
-
title: "No deleted records found",
|
|
2075
|
-
body: "There are no audit records matching your current filters.",
|
|
2076
|
-
action: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: clearFilters, children: "Clear filters" })
|
|
2077
|
-
}
|
|
2078
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2079
|
-
EmptyState,
|
|
2080
|
-
{
|
|
2081
|
-
title: "No deleted records yet",
|
|
2082
|
-
body: "Hard-deleted records will appear here automatically when a monitored database record is permanently deleted."
|
|
2083
|
-
}
|
|
2084
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2085
|
-
/* @__PURE__ */ jsxRuntime.jsx(AuditTable, { items, highlightId, onOpen: openDetail }),
|
|
2086
|
-
/* @__PURE__ */ jsxRuntime.jsx(AuditCards, { items, highlightId, onOpen: openDetail })
|
|
2087
|
-
] }),
|
|
2088
|
-
!error && !isLoading && hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", isLoading: isFetchingMore, onClick: loadMore, children: "Load more" }) }) : null
|
|
2089
|
-
] }) });
|
|
2090
|
-
};
|
|
2091
|
-
const HEADER_CELL = "px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted";
|
|
2092
|
-
const DeletedWhen = ({ occurredAt }) => /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: formatExactDateTime(occurredAt), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cursor-default text-sm text-ui-fg-base", children: formatRelativeTime(occurredAt) }) });
|
|
2093
|
-
const SourceBadge = ({ source }) => {
|
|
2094
|
-
const info = describeSource(source);
|
|
2095
|
-
if (info.kind === "unknown") {
|
|
2096
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Unknown" });
|
|
2097
|
-
}
|
|
2098
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: sourceBadgeColor(info.kind), className: "shrink-0 whitespace-nowrap", children: info.label });
|
|
2099
|
-
};
|
|
2100
|
-
const AuditTable = ({ items, highlightId, onOpen }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden w-full overflow-hidden rounded-xl border border-ui-border-base md:block", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", children: [
|
|
2101
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2102
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[22%]"), children: "Entity" }),
|
|
2103
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[24%]"), children: "Record" }),
|
|
2104
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[13%]"), children: "Deleted" }),
|
|
2105
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[13%]"), children: "Deleted by" }),
|
|
2106
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[11%]"), children: "Source" }),
|
|
2107
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[8%]"), children: "Status" }),
|
|
2108
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[9%]"), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Action" }) })
|
|
2109
|
-
] }) }),
|
|
2110
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((item) => {
|
|
2111
|
-
const entity = getEntityInfo(item.table_name);
|
|
2112
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2113
|
-
"tr",
|
|
2114
|
-
{
|
|
2115
|
-
"data-audit-row": item.id,
|
|
2116
|
-
tabIndex: 0,
|
|
2117
|
-
onClick: () => onOpen(item.id),
|
|
2118
|
-
onKeyDown: (e) => {
|
|
2119
|
-
if (e.key === "Enter") onOpen(item.id);
|
|
2120
|
-
},
|
|
2121
|
-
className: ui.clx(
|
|
2122
|
-
"cursor-pointer outline-none transition-colors hover:bg-ui-bg-subtle/60 focus-visible:bg-ui-bg-subtle",
|
|
2123
|
-
highlightId === item.id && "bg-ui-bg-highlight"
|
|
2124
|
-
),
|
|
2125
|
-
children: [
|
|
2126
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
2127
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-ui-fg-base", title: entity.label, children: entity.label }),
|
|
2128
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-ui-fg-muted", children: entity.category.label })
|
|
2129
|
-
] }) }),
|
|
2130
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: item.record_id }) }),
|
|
2131
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(DeletedWhen, { occurredAt: item.occurred_at }) }),
|
|
2132
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-sm", title: item.deleted_by ?? void 0, children: item.deleted_by ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: item.deleted_by }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "Unknown" }) }),
|
|
2133
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(SourceBadge, { source: item.source }) }),
|
|
2134
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "red", children: "Deleted" }) }),
|
|
2135
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-0.5 whitespace-nowrap text-sm font-medium text-ui-fg-interactive", children: [
|
|
2136
|
-
"View",
|
|
2137
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
2138
|
-
] }) })
|
|
2139
|
-
]
|
|
2140
|
-
},
|
|
2141
|
-
item.id
|
|
2142
|
-
);
|
|
2143
|
-
}) })
|
|
2144
|
-
] }) });
|
|
2145
|
-
const AuditCards = ({ items, highlightId, onOpen }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-2 md:hidden", children: items.map((item) => {
|
|
2146
|
-
const entity = getEntityInfo(item.table_name);
|
|
2147
|
-
return /* @__PURE__ */ jsxRuntime.jsx("li", { "data-audit-row": item.id, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2148
|
-
"div",
|
|
2149
|
-
{
|
|
2150
|
-
role: "button",
|
|
2151
|
-
tabIndex: 0,
|
|
2152
|
-
onClick: () => onOpen(item.id),
|
|
2153
|
-
onKeyDown: (e) => {
|
|
2154
|
-
if (e.key === "Enter") onOpen(item.id);
|
|
2155
|
-
},
|
|
2156
|
-
className: ui.clx(
|
|
2157
|
-
"flex w-full flex-col gap-2 rounded-lg border border-ui-border-base p-3 text-left outline-none hover:bg-ui-bg-subtle/60 focus-visible:bg-ui-bg-subtle",
|
|
2158
|
-
highlightId === item.id && "bg-ui-bg-highlight"
|
|
2159
|
-
),
|
|
2160
|
-
children: [
|
|
2161
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
2162
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
2163
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-ui-fg-base", children: entity.label }),
|
|
2164
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ui-fg-muted", children: entity.category.label })
|
|
2165
|
-
] }),
|
|
2166
|
-
/* @__PURE__ */ jsxRuntime.jsx(DeletedWhen, { occurredAt: item.occurred_at })
|
|
2167
|
-
] }),
|
|
2168
|
-
/* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: item.record_id }),
|
|
2169
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2170
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2171
|
-
/* @__PURE__ */ jsxRuntime.jsx(SourceBadge, { source: item.source }),
|
|
2172
|
-
item.deleted_by ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate text-xs text-ui-fg-subtle", children: [
|
|
2173
|
-
"by ",
|
|
2174
|
-
item.deleted_by
|
|
2175
|
-
] }) : null
|
|
2176
|
-
] }),
|
|
2177
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center whitespace-nowrap text-sm font-medium text-ui-fg-interactive", children: [
|
|
2178
|
-
"View details",
|
|
2179
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
2180
|
-
] })
|
|
2181
|
-
] })
|
|
2182
|
-
]
|
|
2183
|
-
}
|
|
2184
|
-
) }, item.id);
|
|
2185
|
-
}) });
|
|
2186
|
-
const ListSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0 overflow-hidden rounded-xl border border-ui-border-base", "aria-busy": "true", children: [
|
|
2187
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-ui-bg-subtle px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-40" }) }),
|
|
2188
|
-
Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 border-t border-ui-border-subtle px-3 py-4", children: [
|
|
2189
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-[22%] flex-col gap-1.5", children: [
|
|
2190
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-28" }),
|
|
2191
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-16" })
|
|
2192
|
-
] }),
|
|
2193
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-[20%]" }),
|
|
2194
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-[10%]" }),
|
|
2195
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "hidden h-3.5 w-[10%] md:block" }),
|
|
2196
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "hidden h-5 w-14 rounded-full md:block" })
|
|
2197
|
-
] }, i))
|
|
2198
|
-
] });
|
|
2199
|
-
const EmptyState = ({ title, body, action }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-dashed border-ui-border-strong px-6 py-12 text-center", children: [
|
|
2200
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.MagnifierAlert, { className: "text-ui-fg-muted" }),
|
|
2201
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: title }),
|
|
2202
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: body }),
|
|
2203
|
-
action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: action }) : null
|
|
2204
|
-
] });
|
|
2205
|
-
const ErrorState = ({ onRetry, detail }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-ui-border-base px-6 py-12 text-center", children: [
|
|
2206
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: "text-ui-fg-error" }),
|
|
2207
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Unable to load deleted records" }),
|
|
2208
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: "We couldn’t retrieve the audit records right now. Check your connection and try again." }),
|
|
2209
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: detail }),
|
|
2210
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", className: "mt-2", onClick: onRetry, children: "Try again" })
|
|
2211
|
-
] });
|
|
2212
|
-
const config$9 = adminSdk.defineRouteConfig({
|
|
2213
|
-
label: "Deleted Records",
|
|
2214
|
-
icon: icons.Trash
|
|
2215
|
-
});
|
|
2216
927
|
const useDebounce$3 = (value, delay) => {
|
|
2217
928
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
2218
929
|
react.useEffect(() => {
|
|
@@ -2409,7 +1120,7 @@ const PaymentsPage = () => {
|
|
|
2409
1120
|
) }) : null
|
|
2410
1121
|
] }) });
|
|
2411
1122
|
};
|
|
2412
|
-
const config$
|
|
1123
|
+
const config$9 = adminSdk.defineRouteConfig({
|
|
2413
1124
|
label: "Payments",
|
|
2414
1125
|
icon: icons.CreditCard
|
|
2415
1126
|
});
|
|
@@ -2634,320 +1345,1609 @@ const RefundsPage = () => {
|
|
|
2634
1345
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[11%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
2635
1346
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "w-[8%] min-w-0 px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2636
1347
|
] }) }),
|
|
2637
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1348
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1349
|
+
"tr",
|
|
1350
|
+
{
|
|
1351
|
+
className: "cursor-pointer hover:bg-ui-bg-subtle/60",
|
|
1352
|
+
onClick: () => navigate(`/refunds/${r.refund_id}`),
|
|
1353
|
+
children: [
|
|
1354
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-base", title: r.refund_id, children: r.refund_id }),
|
|
1355
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-medium text-ui-fg-base", title: r.order_id ?? void 0, children: r.order_id ?? "—" }),
|
|
1356
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 font-mono text-sm text-ui-fg-subtle", title: r.payment_id, children: r.payment_id }),
|
|
1357
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", children: displayAmount(r) }),
|
|
1358
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
1359
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
1360
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1361
|
+
ui.Badge,
|
|
1362
|
+
{
|
|
1363
|
+
size: "2xsmall",
|
|
1364
|
+
className: `uppercase ${getStatusBadgeClass$6(displayStatus(r))}`,
|
|
1365
|
+
children: displayStatus(r) !== "—" ? displayStatus(r).replace(/_/g, " ") : "—"
|
|
1366
|
+
}
|
|
1367
|
+
) }),
|
|
1368
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.note ?? void 0, children: r.note ?? "—" }),
|
|
1369
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle text-xs", children: new Date(r.created_at).toLocaleDateString("en-US", {
|
|
1370
|
+
month: "short",
|
|
1371
|
+
day: "numeric",
|
|
1372
|
+
hour: "numeric",
|
|
1373
|
+
minute: "2-digit",
|
|
1374
|
+
hour12: true
|
|
1375
|
+
}) }),
|
|
1376
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
1377
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1378
|
+
ui.Button,
|
|
1379
|
+
{
|
|
1380
|
+
variant: "transparent",
|
|
1381
|
+
size: "small",
|
|
1382
|
+
onClick: (e) => {
|
|
1383
|
+
e.stopPropagation();
|
|
1384
|
+
navigate(`/refunds/${r.refund_id}`);
|
|
1385
|
+
},
|
|
1386
|
+
children: "Details"
|
|
1387
|
+
}
|
|
1388
|
+
),
|
|
1389
|
+
r.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1390
|
+
ui.Button,
|
|
1391
|
+
{
|
|
1392
|
+
variant: "transparent",
|
|
1393
|
+
size: "small",
|
|
1394
|
+
onClick: (e) => {
|
|
1395
|
+
e.stopPropagation();
|
|
1396
|
+
navigate(`/orders/${r.order_id}`);
|
|
1397
|
+
},
|
|
1398
|
+
children: "Order"
|
|
1399
|
+
}
|
|
1400
|
+
) : null
|
|
1401
|
+
] }) })
|
|
1402
|
+
]
|
|
1403
|
+
},
|
|
1404
|
+
r.refund_id
|
|
1405
|
+
)) })
|
|
1406
|
+
] }) }),
|
|
1407
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1408
|
+
ui.Button,
|
|
1409
|
+
{
|
|
1410
|
+
variant: "secondary",
|
|
1411
|
+
isLoading: isFetchingMore,
|
|
1412
|
+
onClick: () => loadRefunds(offset, false),
|
|
1413
|
+
children: "Load more"
|
|
1414
|
+
}
|
|
1415
|
+
) }) : null
|
|
1416
|
+
] }) });
|
|
1417
|
+
};
|
|
1418
|
+
const config$8 = adminSdk.defineRouteConfig({
|
|
1419
|
+
label: "Refunds",
|
|
1420
|
+
icon: icons.Receipt
|
|
1421
|
+
});
|
|
1422
|
+
const useDebounce$1 = (value, delay) => {
|
|
1423
|
+
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
1424
|
+
react.useEffect(() => {
|
|
1425
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
1426
|
+
return () => clearTimeout(handler);
|
|
1427
|
+
}, [value, delay]);
|
|
1428
|
+
return debouncedValue;
|
|
1429
|
+
};
|
|
1430
|
+
const getStatusBadgeClass$5 = (status) => {
|
|
1431
|
+
const statusLower = status.toLowerCase();
|
|
1432
|
+
if (statusLower === "requested") {
|
|
1433
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
1434
|
+
}
|
|
1435
|
+
if (statusLower === "received") {
|
|
1436
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
1437
|
+
}
|
|
1438
|
+
if (statusLower === "requires_action") {
|
|
1439
|
+
return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
1440
|
+
}
|
|
1441
|
+
if (statusLower === "completed") {
|
|
1442
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
1443
|
+
}
|
|
1444
|
+
if (statusLower === "canceled") {
|
|
1445
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
1446
|
+
}
|
|
1447
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
1448
|
+
};
|
|
1449
|
+
const ReturnsPage = () => {
|
|
1450
|
+
const navigate = reactRouterDom.useNavigate();
|
|
1451
|
+
const [items, setItems] = react.useState([]);
|
|
1452
|
+
const [statusFilter, setStatusFilter] = react.useState("all");
|
|
1453
|
+
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
1454
|
+
const [searchQuery, setSearchQuery] = react.useState("");
|
|
1455
|
+
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
1456
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
1457
|
+
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
1458
|
+
const [error, setError] = react.useState(null);
|
|
1459
|
+
const [offset, setOffset] = react.useState(0);
|
|
1460
|
+
const [count, setCount] = react.useState(0);
|
|
1461
|
+
const limit = 50;
|
|
1462
|
+
const loadReturns = react.useCallback(
|
|
1463
|
+
async (nextOffset, replace = false) => {
|
|
1464
|
+
try {
|
|
1465
|
+
if (replace) {
|
|
1466
|
+
setIsLoading(true);
|
|
1467
|
+
} else {
|
|
1468
|
+
setIsFetchingMore(true);
|
|
1469
|
+
}
|
|
1470
|
+
setError(null);
|
|
1471
|
+
const params = new URLSearchParams();
|
|
1472
|
+
params.set("limit", String(limit));
|
|
1473
|
+
params.set("offset", String(nextOffset));
|
|
1474
|
+
if (statusFilter !== "all") {
|
|
1475
|
+
params.set("status", statusFilter);
|
|
1476
|
+
}
|
|
1477
|
+
if (debouncedSearchQuery.trim()) {
|
|
1478
|
+
params.set("q", debouncedSearchQuery.trim());
|
|
1479
|
+
}
|
|
1480
|
+
if (createdByFilter !== "all") {
|
|
1481
|
+
params.set("created_by", createdByFilter);
|
|
1482
|
+
}
|
|
1483
|
+
params.set("order", "created_at");
|
|
1484
|
+
const response = await fetch(
|
|
1485
|
+
`/admin/return?${params.toString()}`,
|
|
1486
|
+
{ credentials: "include" }
|
|
1487
|
+
);
|
|
1488
|
+
if (!response.ok) {
|
|
1489
|
+
const message = await response.text();
|
|
1490
|
+
throw new Error(message || "Unable to load return orders");
|
|
1491
|
+
}
|
|
1492
|
+
const payload = await response.json();
|
|
1493
|
+
setCount(payload.count ?? 0);
|
|
1494
|
+
setOffset(nextOffset + (payload.returns?.length ?? 0));
|
|
1495
|
+
setItems(
|
|
1496
|
+
(prev) => replace ? payload.returns ?? [] : [...prev, ...payload.returns ?? []]
|
|
1497
|
+
);
|
|
1498
|
+
} catch (loadError) {
|
|
1499
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load return orders";
|
|
1500
|
+
setError(message);
|
|
1501
|
+
} finally {
|
|
1502
|
+
setIsLoading(false);
|
|
1503
|
+
setIsFetchingMore(false);
|
|
1504
|
+
}
|
|
1505
|
+
},
|
|
1506
|
+
[statusFilter, createdByFilter, debouncedSearchQuery]
|
|
1507
|
+
);
|
|
1508
|
+
react.useEffect(() => {
|
|
1509
|
+
void loadReturns(0, true);
|
|
1510
|
+
}, [statusFilter, createdByFilter, debouncedSearchQuery, loadReturns]);
|
|
1511
|
+
const hasMore = react.useMemo(() => offset < count, [offset, count]);
|
|
1512
|
+
const availableStatuses = react.useMemo(() => {
|
|
1513
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
1514
|
+
items.forEach((item) => statuses.add(item.status));
|
|
1515
|
+
return Array.from(statuses).sort();
|
|
1516
|
+
}, [items]);
|
|
1517
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
1518
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1519
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1520
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Return Orders" }),
|
|
1521
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "View and manage all customer return orders" })
|
|
1522
|
+
] }),
|
|
1523
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => loadReturns(0, true), children: "Refresh" })
|
|
1524
|
+
] }),
|
|
1525
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
1526
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1527
|
+
ui.Input,
|
|
1528
|
+
{
|
|
1529
|
+
placeholder: "Search by return ID, order ID, or customer email",
|
|
1530
|
+
value: searchQuery,
|
|
1531
|
+
onChange: (event) => setSearchQuery(event.target.value),
|
|
1532
|
+
className: "md:max-w-sm"
|
|
1533
|
+
}
|
|
1534
|
+
),
|
|
1535
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
1536
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1537
|
+
"select",
|
|
1538
|
+
{
|
|
1539
|
+
value: createdByFilter,
|
|
1540
|
+
onChange: (event) => setCreatedByFilter(event.target.value),
|
|
1541
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1542
|
+
children: [
|
|
1543
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All (Created by)" }),
|
|
1544
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "customer", children: "Customer" }),
|
|
1545
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
1546
|
+
]
|
|
1547
|
+
}
|
|
1548
|
+
),
|
|
1549
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1550
|
+
"select",
|
|
1551
|
+
{
|
|
1552
|
+
value: statusFilter,
|
|
1553
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
1554
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
1555
|
+
children: [
|
|
1556
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Statuses" }),
|
|
1557
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: status, children: status.replace(/_/g, " ").toUpperCase() }, status))
|
|
1558
|
+
]
|
|
1559
|
+
}
|
|
1560
|
+
)
|
|
1561
|
+
] })
|
|
1562
|
+
] }),
|
|
1563
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
1564
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
1565
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1566
|
+
ui.Button,
|
|
1567
|
+
{
|
|
1568
|
+
variant: "secondary",
|
|
1569
|
+
onClick: () => loadReturns(0, true),
|
|
1570
|
+
children: "Try again"
|
|
1571
|
+
}
|
|
1572
|
+
) })
|
|
1573
|
+
] }) : null,
|
|
1574
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading return orders..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
1575
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "text-xl", children: "No return orders yet" }),
|
|
1576
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Return orders created by customers will appear here." })
|
|
1577
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
1578
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1579
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Return ID" }),
|
|
1580
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Order ID" }),
|
|
1581
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Customer" }),
|
|
1582
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
1583
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Refund Amount" }),
|
|
1584
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
1585
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
1586
|
+
] }) }),
|
|
1587
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2638
1588
|
"tr",
|
|
2639
1589
|
{
|
|
2640
|
-
className: "
|
|
2641
|
-
onClick: () => navigate(`/
|
|
1590
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
1591
|
+
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
2642
1592
|
children: [
|
|
2643
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2644
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2645
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2646
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2647
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle uppercase", children: r.currency_code || "—" }),
|
|
2648
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-ui-fg-subtle", title: r.provider_id || void 0, children: r.provider_id || "—" }),
|
|
2649
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1593
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: returnOrder.id }) }) }),
|
|
1594
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
1595
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
1596
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2650
1597
|
ui.Badge,
|
|
2651
1598
|
{
|
|
2652
1599
|
size: "2xsmall",
|
|
2653
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
2654
|
-
children:
|
|
1600
|
+
className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
|
|
1601
|
+
children: returnOrder.status.replace(/_/g, " ")
|
|
2655
1602
|
}
|
|
2656
1603
|
) }),
|
|
2657
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2658
|
-
|
|
1604
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
1605
|
+
const calc = returnOrder.refund;
|
|
1606
|
+
if (calc?.is_processed && calc.final_refund_amount != null) {
|
|
1607
|
+
return formatRefundCurrency(
|
|
1608
|
+
calc.final_refund_amount,
|
|
1609
|
+
calc.currency_code || returnOrder.currency_code
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1612
|
+
if (calc) {
|
|
1613
|
+
return "Pending";
|
|
1614
|
+
}
|
|
1615
|
+
if (returnOrder.refund_amount == null) {
|
|
1616
|
+
return "—";
|
|
1617
|
+
}
|
|
1618
|
+
return formatRefundCurrency(
|
|
1619
|
+
Number(returnOrder.refund_amount),
|
|
1620
|
+
returnOrder.currency_code
|
|
1621
|
+
);
|
|
1622
|
+
})() }),
|
|
1623
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
1624
|
+
year: "numeric",
|
|
2659
1625
|
month: "short",
|
|
2660
1626
|
day: "numeric",
|
|
2661
1627
|
hour: "numeric",
|
|
2662
1628
|
minute: "2-digit",
|
|
2663
1629
|
hour12: true
|
|
2664
1630
|
}) }),
|
|
2665
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
1631
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1632
|
+
ui.Button,
|
|
1633
|
+
{
|
|
1634
|
+
variant: "transparent",
|
|
1635
|
+
size: "small",
|
|
1636
|
+
onClick: (e) => {
|
|
1637
|
+
e.stopPropagation();
|
|
1638
|
+
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
1639
|
+
},
|
|
1640
|
+
children: "Go to order"
|
|
1641
|
+
}
|
|
1642
|
+
) })
|
|
1643
|
+
]
|
|
1644
|
+
},
|
|
1645
|
+
returnOrder.id
|
|
1646
|
+
)) })
|
|
1647
|
+
] }) }),
|
|
1648
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1649
|
+
ui.Button,
|
|
1650
|
+
{
|
|
1651
|
+
variant: "secondary",
|
|
1652
|
+
isLoading: isFetchingMore,
|
|
1653
|
+
onClick: () => loadReturns(offset, false),
|
|
1654
|
+
children: "Load more"
|
|
1655
|
+
}
|
|
1656
|
+
) }) : null
|
|
1657
|
+
] }) });
|
|
1658
|
+
};
|
|
1659
|
+
const config$7 = adminSdk.defineRouteConfig({
|
|
1660
|
+
label: "Return Orders",
|
|
1661
|
+
icon: icons.ArrowPath
|
|
1662
|
+
});
|
|
1663
|
+
const AUDITED_TABLE_NAMES = [
|
|
1664
|
+
"account_deletion_request",
|
|
1665
|
+
"account_holder",
|
|
1666
|
+
"api_key",
|
|
1667
|
+
"application_method_buy_rules",
|
|
1668
|
+
"application_method_target_rules",
|
|
1669
|
+
"auth_identity",
|
|
1670
|
+
"auth_mfa_factor",
|
|
1671
|
+
"auth_mfa_recovery_code",
|
|
1672
|
+
"auth_password_reset_token",
|
|
1673
|
+
"auth_verification",
|
|
1674
|
+
"cancel_order_reason_mapping",
|
|
1675
|
+
"capture",
|
|
1676
|
+
"cart",
|
|
1677
|
+
"cart_address",
|
|
1678
|
+
"cart_line_item",
|
|
1679
|
+
"cart_line_item_adjustment",
|
|
1680
|
+
"cart_line_item_tax_line",
|
|
1681
|
+
"cart_payment_collection",
|
|
1682
|
+
"cart_promotion",
|
|
1683
|
+
"cart_shipping_method",
|
|
1684
|
+
"cart_shipping_method_adjustment",
|
|
1685
|
+
"cart_shipping_method_tax_line",
|
|
1686
|
+
"contact_email_subscription",
|
|
1687
|
+
"contact_request",
|
|
1688
|
+
"contact_request_comment",
|
|
1689
|
+
"credit_line",
|
|
1690
|
+
"currency",
|
|
1691
|
+
"customer",
|
|
1692
|
+
"customer_account_holder",
|
|
1693
|
+
"customer_address",
|
|
1694
|
+
"customer_group",
|
|
1695
|
+
"customer_group_customer",
|
|
1696
|
+
"dynamic_config_value",
|
|
1697
|
+
"fulfillment",
|
|
1698
|
+
"fulfillment_address",
|
|
1699
|
+
"fulfillment_item",
|
|
1700
|
+
"fulfillment_label",
|
|
1701
|
+
"fulfillment_provider",
|
|
1702
|
+
"fulfillment_set",
|
|
1703
|
+
"geo_zone",
|
|
1704
|
+
"image",
|
|
1705
|
+
"inventory_count_item",
|
|
1706
|
+
"inventory_count_session",
|
|
1707
|
+
"inventory_item",
|
|
1708
|
+
"inventory_level",
|
|
1709
|
+
"inventory_movement",
|
|
1710
|
+
"inventory_purchase",
|
|
1711
|
+
"inventory_purchase_attachment",
|
|
1712
|
+
"inventory_purchase_audit_event",
|
|
1713
|
+
"inventory_purchase_batch",
|
|
1714
|
+
"inventory_purchase_line_item",
|
|
1715
|
+
"invite",
|
|
1716
|
+
"invite_rbac_role",
|
|
1717
|
+
"invoice",
|
|
1718
|
+
"invoice_sequence",
|
|
1719
|
+
"layout_configuration",
|
|
1720
|
+
"link_module_migrations",
|
|
1721
|
+
"location_fulfillment_provider",
|
|
1722
|
+
"location_fulfillment_set",
|
|
1723
|
+
"loyalty_gift_card",
|
|
1724
|
+
"mikro_orm_migrations",
|
|
1725
|
+
"notification",
|
|
1726
|
+
"notification_provider",
|
|
1727
|
+
"notification_tokens",
|
|
1728
|
+
"order",
|
|
1729
|
+
"order_address",
|
|
1730
|
+
"order_cart",
|
|
1731
|
+
"order_change",
|
|
1732
|
+
"order_change_action",
|
|
1733
|
+
"order_claim",
|
|
1734
|
+
"order_claim_item",
|
|
1735
|
+
"order_claim_item_image",
|
|
1736
|
+
"order_credit_line",
|
|
1737
|
+
"order_exchange",
|
|
1738
|
+
"order_exchange_item",
|
|
1739
|
+
"order_fulfillment",
|
|
1740
|
+
"order_item",
|
|
1741
|
+
"order_line_item",
|
|
1742
|
+
"order_line_item_adjustment",
|
|
1743
|
+
"order_line_item_tax_line",
|
|
1744
|
+
"order_payment_collection",
|
|
1745
|
+
"order_promotion",
|
|
1746
|
+
"order_shipping",
|
|
1747
|
+
"order_shipping_method",
|
|
1748
|
+
"order_shipping_method_adjustment",
|
|
1749
|
+
"order_shipping_method_tax_line",
|
|
1750
|
+
"order_summary",
|
|
1751
|
+
"order_transaction",
|
|
1752
|
+
"otp_verification",
|
|
1753
|
+
"payment",
|
|
1754
|
+
"payment_collection",
|
|
1755
|
+
"payment_collection_payment_providers",
|
|
1756
|
+
"payment_detail",
|
|
1757
|
+
"payment_provider",
|
|
1758
|
+
"payment_session",
|
|
1759
|
+
"payout_request",
|
|
1760
|
+
"price",
|
|
1761
|
+
"price_list",
|
|
1762
|
+
"price_list_rule",
|
|
1763
|
+
"price_preference",
|
|
1764
|
+
"price_rule",
|
|
1765
|
+
"price_set",
|
|
1766
|
+
"product",
|
|
1767
|
+
"product_category",
|
|
1768
|
+
"product_category_product",
|
|
1769
|
+
"product_collection",
|
|
1770
|
+
"product_display_priority",
|
|
1771
|
+
"product_option",
|
|
1772
|
+
"product_option_value",
|
|
1773
|
+
"product_product_option",
|
|
1774
|
+
"product_product_option_value",
|
|
1775
|
+
"product_sales_channel",
|
|
1776
|
+
"product_shipping_profile",
|
|
1777
|
+
"product_tag",
|
|
1778
|
+
"product_tags",
|
|
1779
|
+
"product_type",
|
|
1780
|
+
"product_variant",
|
|
1781
|
+
"product_variant_inventory_item",
|
|
1782
|
+
"product_variant_option",
|
|
1783
|
+
"product_variant_price_set",
|
|
1784
|
+
"product_variant_product_image",
|
|
1785
|
+
"product_view",
|
|
1786
|
+
"promotion",
|
|
1787
|
+
"promotion_application_method",
|
|
1788
|
+
"promotion_campaign",
|
|
1789
|
+
"promotion_campaign_budget",
|
|
1790
|
+
"promotion_campaign_budget_usage",
|
|
1791
|
+
"promotion_promotion_rule",
|
|
1792
|
+
"promotion_rule",
|
|
1793
|
+
"promotion_rule_value",
|
|
1794
|
+
"property_label",
|
|
1795
|
+
"provider_identity",
|
|
1796
|
+
"publishable_api_key_sales_channel",
|
|
1797
|
+
"purchase_supplier",
|
|
1798
|
+
"referral_link",
|
|
1799
|
+
"referral_reward",
|
|
1800
|
+
"refund",
|
|
1801
|
+
"refund_payment_mapping",
|
|
1802
|
+
"refund_reason",
|
|
1803
|
+
"region",
|
|
1804
|
+
"region_country",
|
|
1805
|
+
"region_payment_provider",
|
|
1806
|
+
"reservation_item",
|
|
1807
|
+
"return",
|
|
1808
|
+
"return_fulfillment",
|
|
1809
|
+
"return_item",
|
|
1810
|
+
"return_reason",
|
|
1811
|
+
"review",
|
|
1812
|
+
"sales_channel",
|
|
1813
|
+
"sales_channel_stock_location",
|
|
1814
|
+
"script_migrations",
|
|
1815
|
+
"search_index",
|
|
1816
|
+
"search_index_sync",
|
|
1817
|
+
"search_index_version",
|
|
1818
|
+
"search_postgres_index",
|
|
1819
|
+
"service_zone",
|
|
1820
|
+
"shipment_tracking_event",
|
|
1821
|
+
"shipping_option",
|
|
1822
|
+
"shipping_option_price_set",
|
|
1823
|
+
"shipping_option_rule",
|
|
1824
|
+
"shipping_option_type",
|
|
1825
|
+
"shipping_profile",
|
|
1826
|
+
"skip_merge_cart",
|
|
1827
|
+
"stock_location",
|
|
1828
|
+
"stock_location_address",
|
|
1829
|
+
"store",
|
|
1830
|
+
"store_credit_account",
|
|
1831
|
+
"store_credit_account_transaction",
|
|
1832
|
+
"store_currency",
|
|
1833
|
+
"store_locale",
|
|
1834
|
+
"tax_provider",
|
|
1835
|
+
"tax_rate",
|
|
1836
|
+
"tax_rate_rule",
|
|
1837
|
+
"tax_region",
|
|
1838
|
+
"telegram_config",
|
|
1839
|
+
"telegram_notification_log",
|
|
1840
|
+
"user",
|
|
1841
|
+
"user_preference",
|
|
1842
|
+
"user_rbac_role",
|
|
1843
|
+
"view_configuration",
|
|
1844
|
+
"wallet_account",
|
|
1845
|
+
"wallet_credit_lot",
|
|
1846
|
+
"wallet_gift_card",
|
|
1847
|
+
"wallet_hold",
|
|
1848
|
+
"wallet_ledger_entry",
|
|
1849
|
+
"wallet_rate_limit",
|
|
1850
|
+
"wallet_refund_intent",
|
|
1851
|
+
"wallet_top_up_request",
|
|
1852
|
+
"wishlist",
|
|
1853
|
+
"workflow_execution"
|
|
1854
|
+
];
|
|
1855
|
+
const ENTITY_CATEGORIES = [
|
|
1856
|
+
{ id: "orders", label: "Orders", description: "Orders, items, returns, exchanges and claims" },
|
|
1857
|
+
{ id: "carts", label: "Carts", description: "Shopping carts and checkout data" },
|
|
1858
|
+
{ id: "customers", label: "Customers", description: "Customers, addresses and groups" },
|
|
1859
|
+
{ id: "catalog", label: "Catalog", description: "Products, variants, categories and collections" },
|
|
1860
|
+
{ id: "pricing", label: "Pricing & Promotions", description: "Prices, price lists and promotions" },
|
|
1861
|
+
{ id: "payments", label: "Payments & Refunds", description: "Payments, sessions, captures and refunds" },
|
|
1862
|
+
{ id: "fulfillment", label: "Fulfillment & Shipping", description: "Fulfillments, shipping options and tracking" },
|
|
1863
|
+
{ id: "inventory", label: "Inventory & Purchasing", description: "Stock, locations, reservations and purchases" },
|
|
1864
|
+
{ id: "wallet", label: "Wallet & Credits", description: "Wallets, store credit and gift cards" },
|
|
1865
|
+
{ id: "access", label: "Users & Access", description: "Admin users, logins, roles and API keys" },
|
|
1866
|
+
{ id: "store", label: "Store & Regions", description: "Store, regions, currencies, taxes and sales channels" },
|
|
1867
|
+
{ id: "engagement", label: "Engagement", description: "Reviews, wishlists, referrals and contact requests" },
|
|
1868
|
+
{ id: "notifications", label: "Notifications", description: "Notifications and messaging" },
|
|
1869
|
+
{ id: "system", label: "System & Configuration", description: "Settings, search, workflows and migrations" }
|
|
1870
|
+
];
|
|
1871
|
+
const ENTITY_DEFINITIONS = {
|
|
1872
|
+
// Orders
|
|
1873
|
+
order: { label: "Order", category: "orders" },
|
|
1874
|
+
order_address: { label: "Order Address", category: "orders" },
|
|
1875
|
+
order_cart: { label: "Order–Cart Link", category: "orders" },
|
|
1876
|
+
order_change: { label: "Order Change", category: "orders" },
|
|
1877
|
+
order_change_action: { label: "Order Change Action", category: "orders" },
|
|
1878
|
+
order_claim: { label: "Claim", category: "orders" },
|
|
1879
|
+
order_claim_item: { label: "Claim Item", category: "orders" },
|
|
1880
|
+
order_claim_item_image: { label: "Claim Item Image", category: "orders" },
|
|
1881
|
+
order_credit_line: { label: "Order Credit Line", category: "orders" },
|
|
1882
|
+
order_exchange: { label: "Exchange", category: "orders" },
|
|
1883
|
+
order_exchange_item: { label: "Exchange Item", category: "orders" },
|
|
1884
|
+
order_fulfillment: { label: "Order–Fulfillment Link", category: "orders" },
|
|
1885
|
+
order_item: { label: "Order Item Quantity", category: "orders" },
|
|
1886
|
+
order_line_item: { label: "Order Item", category: "orders" },
|
|
1887
|
+
order_line_item_adjustment: { label: "Order Item Discount", category: "orders" },
|
|
1888
|
+
order_line_item_tax_line: { label: "Order Item Tax", category: "orders" },
|
|
1889
|
+
order_payment_collection: { label: "Order–Payment Link", category: "orders" },
|
|
1890
|
+
order_promotion: { label: "Order Promotion", category: "orders" },
|
|
1891
|
+
order_shipping: { label: "Order Shipping", category: "orders" },
|
|
1892
|
+
order_shipping_method: { label: "Order Shipping Method", category: "orders" },
|
|
1893
|
+
order_shipping_method_adjustment: { label: "Order Shipping Discount", category: "orders" },
|
|
1894
|
+
order_shipping_method_tax_line: { label: "Order Shipping Tax", category: "orders" },
|
|
1895
|
+
order_summary: { label: "Order Summary", category: "orders" },
|
|
1896
|
+
order_transaction: { label: "Order Transaction", category: "orders" },
|
|
1897
|
+
return: { label: "Return", category: "orders" },
|
|
1898
|
+
return_fulfillment: { label: "Return–Fulfillment Link", category: "orders" },
|
|
1899
|
+
return_item: { label: "Return Item", category: "orders" },
|
|
1900
|
+
return_reason: { label: "Return Reason", category: "orders" },
|
|
1901
|
+
cancel_order_reason_mapping: { label: "Order Cancellation Reason", category: "orders" },
|
|
1902
|
+
credit_line: { label: "Credit Line", category: "orders" },
|
|
1903
|
+
invoice: { label: "Invoice", category: "orders" },
|
|
1904
|
+
invoice_sequence: { label: "Invoice Number Sequence", category: "orders" },
|
|
1905
|
+
// Carts
|
|
1906
|
+
cart: { label: "Cart", category: "carts" },
|
|
1907
|
+
cart_address: { label: "Cart Address", category: "carts" },
|
|
1908
|
+
cart_line_item: { label: "Cart Item", category: "carts" },
|
|
1909
|
+
cart_line_item_adjustment: { label: "Cart Item Discount", category: "carts" },
|
|
1910
|
+
cart_line_item_tax_line: { label: "Cart Item Tax", category: "carts" },
|
|
1911
|
+
cart_payment_collection: { label: "Cart–Payment Link", category: "carts" },
|
|
1912
|
+
cart_promotion: { label: "Cart Promotion", category: "carts" },
|
|
1913
|
+
cart_shipping_method: { label: "Cart Shipping Method", category: "carts" },
|
|
1914
|
+
cart_shipping_method_adjustment: { label: "Cart Shipping Discount", category: "carts" },
|
|
1915
|
+
cart_shipping_method_tax_line: { label: "Cart Shipping Tax", category: "carts" },
|
|
1916
|
+
skip_merge_cart: { label: "Cart Merge Exclusion", category: "carts" },
|
|
1917
|
+
// Customers
|
|
1918
|
+
customer: { label: "Customer", category: "customers" },
|
|
1919
|
+
customer_address: { label: "Customer Address", category: "customers" },
|
|
1920
|
+
customer_group: { label: "Customer Group", category: "customers" },
|
|
1921
|
+
customer_group_customer: { label: "Customer Group Member", category: "customers" },
|
|
1922
|
+
customer_account_holder: { label: "Customer–Account Holder Link", category: "customers" },
|
|
1923
|
+
account_holder: { label: "Payment Account Holder", category: "customers" },
|
|
1924
|
+
account_deletion_request: { label: "Account Deletion Request", category: "customers" },
|
|
1925
|
+
payment_detail: { label: "Customer Refund Method", category: "customers" },
|
|
1926
|
+
otp_verification: { label: "OTP Verification", category: "customers" },
|
|
1927
|
+
// Catalog
|
|
1928
|
+
product: { label: "Product", category: "catalog" },
|
|
1929
|
+
product_variant: { label: "Product Variant", category: "catalog" },
|
|
1930
|
+
product_category: { label: "Product Category", category: "catalog" },
|
|
1931
|
+
product_category_product: { label: "Product–Category Link", category: "catalog" },
|
|
1932
|
+
product_collection: { label: "Collection", category: "catalog" },
|
|
1933
|
+
product_option: { label: "Product Option", category: "catalog" },
|
|
1934
|
+
product_option_value: { label: "Product Option Value", category: "catalog" },
|
|
1935
|
+
product_product_option: { label: "Product–Option Link", category: "catalog" },
|
|
1936
|
+
product_product_option_value: { label: "Product–Option Value Link", category: "catalog" },
|
|
1937
|
+
product_tag: { label: "Product Tag", category: "catalog" },
|
|
1938
|
+
product_tags: { label: "Product–Tag Link", category: "catalog" },
|
|
1939
|
+
product_type: { label: "Product Type", category: "catalog" },
|
|
1940
|
+
product_sales_channel: { label: "Product–Sales Channel Link", category: "catalog" },
|
|
1941
|
+
product_shipping_profile: { label: "Product–Shipping Profile Link", category: "catalog" },
|
|
1942
|
+
product_variant_inventory_item: { label: "Variant–Inventory Link", category: "catalog" },
|
|
1943
|
+
product_variant_option: { label: "Variant Option", category: "catalog" },
|
|
1944
|
+
product_variant_price_set: { label: "Variant–Price Link", category: "catalog" },
|
|
1945
|
+
product_variant_product_image: { label: "Variant Image", category: "catalog" },
|
|
1946
|
+
product_display_priority: { label: "Product Display Priority", category: "catalog" },
|
|
1947
|
+
product_view: { label: "Product View", category: "catalog" },
|
|
1948
|
+
image: { label: "Product Image", category: "catalog" },
|
|
1949
|
+
property_label: { label: "Property Label", category: "catalog" },
|
|
1950
|
+
// Pricing & promotions
|
|
1951
|
+
price: { label: "Price", category: "pricing" },
|
|
1952
|
+
price_list: { label: "Price List", category: "pricing" },
|
|
1953
|
+
price_list_rule: { label: "Price List Rule", category: "pricing" },
|
|
1954
|
+
price_preference: { label: "Price Preference", category: "pricing" },
|
|
1955
|
+
price_rule: { label: "Price Rule", category: "pricing" },
|
|
1956
|
+
price_set: { label: "Price Set", category: "pricing" },
|
|
1957
|
+
promotion: { label: "Promotion", category: "pricing" },
|
|
1958
|
+
promotion_application_method: { label: "Promotion Application Method", category: "pricing" },
|
|
1959
|
+
promotion_campaign: { label: "Campaign", category: "pricing" },
|
|
1960
|
+
promotion_campaign_budget: { label: "Campaign Budget", category: "pricing" },
|
|
1961
|
+
promotion_campaign_budget_usage: { label: "Campaign Budget Usage", category: "pricing" },
|
|
1962
|
+
promotion_promotion_rule: { label: "Promotion–Rule Link", category: "pricing" },
|
|
1963
|
+
promotion_rule: { label: "Promotion Rule", category: "pricing" },
|
|
1964
|
+
promotion_rule_value: { label: "Promotion Rule Value", category: "pricing" },
|
|
1965
|
+
application_method_buy_rules: { label: "Promotion Buy Rule", category: "pricing" },
|
|
1966
|
+
application_method_target_rules: { label: "Promotion Target Rule", category: "pricing" },
|
|
1967
|
+
// Payments
|
|
1968
|
+
payment: { label: "Payment", category: "payments" },
|
|
1969
|
+
payment_collection: { label: "Payment Collection", category: "payments" },
|
|
1970
|
+
payment_collection_payment_providers: { label: "Payment Collection–Provider Link", category: "payments" },
|
|
1971
|
+
payment_provider: { label: "Payment Provider", category: "payments" },
|
|
1972
|
+
payment_session: { label: "Payment Session", category: "payments" },
|
|
1973
|
+
capture: { label: "Payment Capture", category: "payments" },
|
|
1974
|
+
refund: { label: "Refund", category: "payments" },
|
|
1975
|
+
refund_reason: { label: "Refund Reason", category: "payments" },
|
|
1976
|
+
refund_payment_mapping: { label: "Return Refund Mapping", category: "payments" },
|
|
1977
|
+
payout_request: { label: "Payout Request", category: "payments" },
|
|
1978
|
+
// Fulfillment
|
|
1979
|
+
fulfillment: { label: "Fulfillment", category: "fulfillment" },
|
|
1980
|
+
fulfillment_address: { label: "Fulfillment Address", category: "fulfillment" },
|
|
1981
|
+
fulfillment_item: { label: "Fulfillment Item", category: "fulfillment" },
|
|
1982
|
+
fulfillment_label: { label: "Shipping Label", category: "fulfillment" },
|
|
1983
|
+
fulfillment_provider: { label: "Fulfillment Provider", category: "fulfillment" },
|
|
1984
|
+
fulfillment_set: { label: "Fulfillment Set", category: "fulfillment" },
|
|
1985
|
+
geo_zone: { label: "Geo Zone", category: "fulfillment" },
|
|
1986
|
+
service_zone: { label: "Service Zone", category: "fulfillment" },
|
|
1987
|
+
shipping_option: { label: "Shipping Option", category: "fulfillment" },
|
|
1988
|
+
shipping_option_price_set: { label: "Shipping Option–Price Link", category: "fulfillment" },
|
|
1989
|
+
shipping_option_rule: { label: "Shipping Option Rule", category: "fulfillment" },
|
|
1990
|
+
shipping_option_type: { label: "Shipping Option Type", category: "fulfillment" },
|
|
1991
|
+
shipping_profile: { label: "Shipping Profile", category: "fulfillment" },
|
|
1992
|
+
shipment_tracking_event: { label: "Shipment Tracking Event", category: "fulfillment" },
|
|
1993
|
+
location_fulfillment_provider: { label: "Location–Fulfillment Provider Link", category: "fulfillment" },
|
|
1994
|
+
location_fulfillment_set: { label: "Location–Fulfillment Set Link", category: "fulfillment" },
|
|
1995
|
+
// Inventory
|
|
1996
|
+
inventory_item: { label: "Inventory Item", category: "inventory" },
|
|
1997
|
+
inventory_level: { label: "Inventory Level", category: "inventory" },
|
|
1998
|
+
inventory_movement: { label: "Inventory Movement", category: "inventory" },
|
|
1999
|
+
inventory_count_item: { label: "Stock Count Item", category: "inventory" },
|
|
2000
|
+
inventory_count_session: { label: "Stock Count Session", category: "inventory" },
|
|
2001
|
+
inventory_purchase: { label: "Purchase", category: "inventory" },
|
|
2002
|
+
inventory_purchase_attachment: { label: "Purchase Attachment", category: "inventory" },
|
|
2003
|
+
inventory_purchase_audit_event: { label: "Purchase Audit Event", category: "inventory" },
|
|
2004
|
+
inventory_purchase_batch: { label: "Purchase Batch", category: "inventory" },
|
|
2005
|
+
inventory_purchase_line_item: { label: "Purchase Item", category: "inventory" },
|
|
2006
|
+
purchase_supplier: { label: "Supplier", category: "inventory" },
|
|
2007
|
+
reservation_item: { label: "Stock Reservation", category: "inventory" },
|
|
2008
|
+
stock_location: { label: "Stock Location", category: "inventory" },
|
|
2009
|
+
stock_location_address: { label: "Stock Location Address", category: "inventory" },
|
|
2010
|
+
sales_channel_stock_location: { label: "Sales Channel–Location Link", category: "inventory" },
|
|
2011
|
+
// Wallet
|
|
2012
|
+
wallet_account: { label: "Wallet Account", category: "wallet" },
|
|
2013
|
+
wallet_credit_lot: { label: "Wallet Credit Lot", category: "wallet" },
|
|
2014
|
+
wallet_gift_card: { label: "Wallet Gift Card", category: "wallet" },
|
|
2015
|
+
wallet_hold: { label: "Wallet Hold", category: "wallet" },
|
|
2016
|
+
wallet_ledger_entry: { label: "Wallet Ledger Entry", category: "wallet" },
|
|
2017
|
+
wallet_rate_limit: { label: "Wallet Rate Limit", category: "wallet" },
|
|
2018
|
+
wallet_refund_intent: { label: "Wallet Refund", category: "wallet" },
|
|
2019
|
+
wallet_top_up_request: { label: "Wallet Top-up Request", category: "wallet" },
|
|
2020
|
+
store_credit_account: { label: "Store Credit Account", category: "wallet" },
|
|
2021
|
+
store_credit_account_transaction: { label: "Store Credit Transaction", category: "wallet" },
|
|
2022
|
+
loyalty_gift_card: { label: "Loyalty Gift Card", category: "wallet" },
|
|
2023
|
+
// Users & access
|
|
2024
|
+
user: { label: "Admin User", category: "access" },
|
|
2025
|
+
user_preference: { label: "User Preference", category: "access" },
|
|
2026
|
+
user_rbac_role: { label: "User Role", category: "access" },
|
|
2027
|
+
invite: { label: "Admin Invite", category: "access" },
|
|
2028
|
+
invite_rbac_role: { label: "Invite Role", category: "access" },
|
|
2029
|
+
api_key: { label: "API Key", category: "access" },
|
|
2030
|
+
publishable_api_key_sales_channel: { label: "API Key–Sales Channel Link", category: "access" },
|
|
2031
|
+
auth_identity: { label: "Login Identity", category: "access" },
|
|
2032
|
+
auth_mfa_factor: { label: "MFA Factor", category: "access" },
|
|
2033
|
+
auth_mfa_recovery_code: { label: "MFA Recovery Code", category: "access" },
|
|
2034
|
+
auth_password_reset_token: { label: "Password Reset Token", category: "access" },
|
|
2035
|
+
auth_verification: { label: "Auth Verification", category: "access" },
|
|
2036
|
+
provider_identity: { label: "Login Provider Identity", category: "access" },
|
|
2037
|
+
// Store & regions
|
|
2038
|
+
store: { label: "Store", category: "store" },
|
|
2039
|
+
store_currency: { label: "Store Currency", category: "store" },
|
|
2040
|
+
store_locale: { label: "Store Locale", category: "store" },
|
|
2041
|
+
currency: { label: "Currency", category: "store" },
|
|
2042
|
+
region: { label: "Region", category: "store" },
|
|
2043
|
+
region_country: { label: "Region Country", category: "store" },
|
|
2044
|
+
region_payment_provider: { label: "Region–Payment Provider Link", category: "store" },
|
|
2045
|
+
sales_channel: { label: "Sales Channel", category: "store" },
|
|
2046
|
+
tax_provider: { label: "Tax Provider", category: "store" },
|
|
2047
|
+
tax_rate: { label: "Tax Rate", category: "store" },
|
|
2048
|
+
tax_rate_rule: { label: "Tax Rate Rule", category: "store" },
|
|
2049
|
+
tax_region: { label: "Tax Region", category: "store" },
|
|
2050
|
+
// Engagement
|
|
2051
|
+
review: { label: "Review", category: "engagement" },
|
|
2052
|
+
wishlist: { label: "Wishlist", category: "engagement" },
|
|
2053
|
+
referral_link: { label: "Referral Link", category: "engagement" },
|
|
2054
|
+
referral_reward: { label: "Referral Reward", category: "engagement" },
|
|
2055
|
+
contact_request: { label: "Contact Request", category: "engagement" },
|
|
2056
|
+
contact_request_comment: { label: "Contact Request Comment", category: "engagement" },
|
|
2057
|
+
contact_email_subscription: { label: "Email Subscription", category: "engagement" },
|
|
2058
|
+
// Notifications
|
|
2059
|
+
notification: { label: "Notification", category: "notifications" },
|
|
2060
|
+
notification_provider: { label: "Notification Provider", category: "notifications" },
|
|
2061
|
+
notification_tokens: { label: "Push Notification Token", category: "notifications" },
|
|
2062
|
+
telegram_config: { label: "Telegram Settings", category: "notifications" },
|
|
2063
|
+
telegram_notification_log: { label: "Telegram Notification Log", category: "notifications" },
|
|
2064
|
+
// System
|
|
2065
|
+
dynamic_config_value: { label: "Plugin Setting", category: "system" },
|
|
2066
|
+
layout_configuration: { label: "Layout Configuration", category: "system" },
|
|
2067
|
+
view_configuration: { label: "View Configuration", category: "system" },
|
|
2068
|
+
workflow_execution: { label: "Workflow Execution", category: "system" },
|
|
2069
|
+
search_index: { label: "Search Index", category: "system" },
|
|
2070
|
+
search_index_sync: { label: "Search Index Sync", category: "system" },
|
|
2071
|
+
search_index_version: { label: "Search Index Version", category: "system" },
|
|
2072
|
+
search_postgres_index: { label: "Search Index Entry", category: "system" },
|
|
2073
|
+
link_module_migrations: { label: "Link Migration Record", category: "system" },
|
|
2074
|
+
mikro_orm_migrations: { label: "Database Migration Record", category: "system" },
|
|
2075
|
+
script_migrations: { label: "Script Migration Record", category: "system" }
|
|
2076
|
+
};
|
|
2077
|
+
const CATEGORY_BY_ID = new Map(ENTITY_CATEGORIES.map((c) => [c.id, c]));
|
|
2078
|
+
const SYSTEM_CATEGORY = CATEGORY_BY_ID.get("system");
|
|
2079
|
+
function humanizeTableName(tableName) {
|
|
2080
|
+
return tableName.split("_").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
2081
|
+
}
|
|
2082
|
+
function getEntityInfo(tableName) {
|
|
2083
|
+
const def = ENTITY_DEFINITIONS[tableName];
|
|
2084
|
+
return {
|
|
2085
|
+
tableName,
|
|
2086
|
+
label: def?.label ?? humanizeTableName(tableName),
|
|
2087
|
+
category: def && CATEGORY_BY_ID.get(def.category) || SYSTEM_CATEGORY
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
function getEntitiesByCategory() {
|
|
2091
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2092
|
+
for (const table of AUDITED_TABLE_NAMES) {
|
|
2093
|
+
const info = getEntityInfo(table);
|
|
2094
|
+
const list = groups.get(info.category.id) ?? [];
|
|
2095
|
+
list.push(info);
|
|
2096
|
+
groups.set(info.category.id, list);
|
|
2097
|
+
}
|
|
2098
|
+
return ENTITY_CATEGORIES.filter((category) => groups.has(category.id)).map((category) => ({
|
|
2099
|
+
category,
|
|
2100
|
+
entities: (groups.get(category.id) ?? []).sort((a, b) => a.label.localeCompare(b.label))
|
|
2101
|
+
}));
|
|
2102
|
+
}
|
|
2103
|
+
function getCategory(id) {
|
|
2104
|
+
return CATEGORY_BY_ID.get(id);
|
|
2105
|
+
}
|
|
2106
|
+
function getTablesForCategory(id) {
|
|
2107
|
+
return AUDITED_TABLE_NAMES.filter((table) => getEntityInfo(table).category.id === id);
|
|
2108
|
+
}
|
|
2109
|
+
const GROUPS = getEntitiesByCategory();
|
|
2110
|
+
function triggerLabel(entity, category) {
|
|
2111
|
+
if (entity) return getEntityInfo(entity).label;
|
|
2112
|
+
if (category) return `All ${getCategory(category)?.label ?? category}`;
|
|
2113
|
+
return "All entities";
|
|
2114
|
+
}
|
|
2115
|
+
const EntityPicker = ({ entity, category, onChange }) => {
|
|
2116
|
+
const [open, setOpen] = react.useState(false);
|
|
2117
|
+
const [search, setSearch] = react.useState("");
|
|
2118
|
+
const searchRef = react.useRef(null);
|
|
2119
|
+
const filteredGroups = react.useMemo(() => {
|
|
2120
|
+
const term = search.trim().toLowerCase();
|
|
2121
|
+
if (!term) return GROUPS;
|
|
2122
|
+
return GROUPS.map((group) => {
|
|
2123
|
+
const categoryMatches = group.category.label.toLowerCase().includes(term);
|
|
2124
|
+
const entities = categoryMatches ? group.entities : group.entities.filter(
|
|
2125
|
+
(e) => e.label.toLowerCase().includes(term) || e.tableName.includes(term.replace(/\s+/g, "_"))
|
|
2126
|
+
);
|
|
2127
|
+
return { ...group, entities };
|
|
2128
|
+
}).filter((group) => group.entities.length > 0);
|
|
2129
|
+
}, [search]);
|
|
2130
|
+
const select = (next) => {
|
|
2131
|
+
onChange(next);
|
|
2132
|
+
setOpen(false);
|
|
2133
|
+
setSearch("");
|
|
2134
|
+
};
|
|
2135
|
+
const firstMatch = filteredGroups[0]?.entities[0];
|
|
2136
|
+
const isAll = !entity && !category;
|
|
2137
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2138
|
+
ui.Popover,
|
|
2139
|
+
{
|
|
2140
|
+
open,
|
|
2141
|
+
onOpenChange: (next) => {
|
|
2142
|
+
setOpen(next);
|
|
2143
|
+
if (!next) setSearch("");
|
|
2144
|
+
},
|
|
2145
|
+
children: [
|
|
2146
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2147
|
+
"button",
|
|
2148
|
+
{
|
|
2149
|
+
type: "button",
|
|
2150
|
+
"aria-label": "Filter by entity",
|
|
2151
|
+
className: ui.clx(
|
|
2152
|
+
"txt-compact-small flex h-7 w-full min-w-[200px] items-center justify-between gap-2 rounded-md bg-ui-bg-field px-2 text-left shadow-borders-base outline-none transition-fg",
|
|
2153
|
+
"hover:bg-ui-bg-field-hover focus-visible:shadow-borders-interactive-with-active md:w-auto",
|
|
2154
|
+
isAll ? "text-ui-fg-muted" : "text-ui-fg-base"
|
|
2155
|
+
),
|
|
2156
|
+
children: [
|
|
2157
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: triggerLabel(entity, category) }),
|
|
2158
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDownMini, { className: "shrink-0 text-ui-fg-muted" })
|
|
2159
|
+
]
|
|
2160
|
+
}
|
|
2161
|
+
) }),
|
|
2162
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2163
|
+
ui.Popover.Content,
|
|
2164
|
+
{
|
|
2165
|
+
align: "start",
|
|
2166
|
+
className: "w-[min(360px,calc(100vw-2rem))] p-0",
|
|
2167
|
+
onOpenAutoFocus: (event) => {
|
|
2168
|
+
event.preventDefault();
|
|
2169
|
+
searchRef.current?.focus();
|
|
2170
|
+
},
|
|
2171
|
+
children: [
|
|
2172
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-ui-border-base p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2173
|
+
ui.Input,
|
|
2680
2174
|
{
|
|
2681
|
-
|
|
2175
|
+
ref: searchRef,
|
|
2682
2176
|
size: "small",
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2177
|
+
type: "search",
|
|
2178
|
+
placeholder: "Search entities, e.g. order, wallet…",
|
|
2179
|
+
value: search,
|
|
2180
|
+
onChange: (e) => setSearch(e.target.value),
|
|
2181
|
+
onKeyDown: (e) => {
|
|
2182
|
+
if (e.key === "Enter" && firstMatch) {
|
|
2183
|
+
e.preventDefault();
|
|
2184
|
+
select({ entity: firstMatch.tableName, category: "" });
|
|
2185
|
+
}
|
|
2686
2186
|
},
|
|
2687
|
-
|
|
2187
|
+
"aria-label": "Search entities"
|
|
2688
2188
|
}
|
|
2689
|
-
)
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2189
|
+
) }),
|
|
2190
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[360px] overflow-y-auto p-1", role: "listbox", "aria-label": "Entities", children: [
|
|
2191
|
+
!search.trim() ? /* @__PURE__ */ jsxRuntime.jsx(PickerOption, { selected: isAll, onSelect: () => select({ entity: "", category: "" }), children: "All entities" }) : null,
|
|
2192
|
+
filteredGroups.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "px-3 py-6 text-center text-ui-fg-muted", children: [
|
|
2193
|
+
"No entities match “",
|
|
2194
|
+
search.trim(),
|
|
2195
|
+
"”"
|
|
2196
|
+
] }) : null,
|
|
2197
|
+
filteredGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1", children: [
|
|
2198
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1 pt-2 text-xs font-medium uppercase tracking-wide text-ui-fg-muted", children: group.category.label }),
|
|
2199
|
+
!search.trim() ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2200
|
+
PickerOption,
|
|
2201
|
+
{
|
|
2202
|
+
selected: !entity && category === group.category.id,
|
|
2203
|
+
onSelect: () => select({ entity: "", category: group.category.id }),
|
|
2204
|
+
secondary: group.category.description,
|
|
2205
|
+
children: [
|
|
2206
|
+
"All ",
|
|
2207
|
+
group.category.label
|
|
2208
|
+
]
|
|
2209
|
+
}
|
|
2210
|
+
) : null,
|
|
2211
|
+
group.entities.map((info) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2212
|
+
PickerOption,
|
|
2213
|
+
{
|
|
2214
|
+
selected: entity === info.tableName,
|
|
2215
|
+
onSelect: () => select({ entity: info.tableName, category: "" }),
|
|
2216
|
+
secondary: info.tableName,
|
|
2217
|
+
secondaryMono: true,
|
|
2218
|
+
indent: !search.trim(),
|
|
2219
|
+
children: info.label
|
|
2220
|
+
},
|
|
2221
|
+
info.tableName
|
|
2222
|
+
))
|
|
2223
|
+
] }, group.category.id))
|
|
2224
|
+
] })
|
|
2225
|
+
]
|
|
2226
|
+
}
|
|
2227
|
+
)
|
|
2228
|
+
]
|
|
2229
|
+
}
|
|
2230
|
+
);
|
|
2231
|
+
};
|
|
2232
|
+
const PickerOption = ({ selected, onSelect, children, secondary, secondaryMono, indent }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2233
|
+
"button",
|
|
2234
|
+
{
|
|
2235
|
+
type: "button",
|
|
2236
|
+
role: "option",
|
|
2237
|
+
"aria-selected": selected,
|
|
2238
|
+
onClick: onSelect,
|
|
2239
|
+
className: ui.clx(
|
|
2240
|
+
"flex w-full items-start gap-2 rounded-md px-2 py-1.5 text-left outline-none transition-fg",
|
|
2241
|
+
"hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-hover",
|
|
2242
|
+
indent && "pl-4"
|
|
2243
|
+
),
|
|
2244
|
+
children: [
|
|
2245
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 flex size-4 shrink-0 items-center justify-center text-ui-fg-interactive", children: selected ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}) : null }),
|
|
2246
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
2247
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm text-ui-fg-base", children }),
|
|
2248
|
+
secondary ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.clx("truncate text-xs text-ui-fg-muted", secondaryMono && "font-mono"), children: secondary }) : null
|
|
2249
|
+
] })
|
|
2250
|
+
]
|
|
2251
|
+
}
|
|
2252
|
+
);
|
|
2253
|
+
const CopyableId = ({ value, emptyLabel = "No ID", className }) => {
|
|
2254
|
+
if (!value) {
|
|
2255
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "italic text-ui-fg-muted", children: emptyLabel });
|
|
2256
|
+
}
|
|
2257
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ui.clx("inline-flex min-w-0 max-w-full items-center gap-1", className), children: [
|
|
2258
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-xs text-ui-fg-base", title: value, children: value }),
|
|
2259
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { onClick: (e) => e.stopPropagation(), className: "inline-flex shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Copy, { content: value, variant: "mini", className: "text-ui-fg-muted", "aria-label": `Copy ${value}` }) })
|
|
2260
|
+
] });
|
|
2261
|
+
};
|
|
2262
|
+
const RELATIVE_UNITS = [
|
|
2263
|
+
{ unit: "year", seconds: 60 * 60 * 24 * 365 },
|
|
2264
|
+
{ unit: "month", seconds: 60 * 60 * 24 * 30 },
|
|
2265
|
+
{ unit: "week", seconds: 60 * 60 * 24 * 7 },
|
|
2266
|
+
{ unit: "day", seconds: 60 * 60 * 24 },
|
|
2267
|
+
{ unit: "hour", seconds: 60 * 60 },
|
|
2268
|
+
{ unit: "minute", seconds: 60 }
|
|
2269
|
+
];
|
|
2270
|
+
function toDate(value) {
|
|
2271
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
2272
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
2273
|
+
}
|
|
2274
|
+
function formatRelativeTime(value, now = /* @__PURE__ */ new Date()) {
|
|
2275
|
+
const date = toDate(value);
|
|
2276
|
+
if (!date) return "—";
|
|
2277
|
+
const diffSeconds = Math.round((date.getTime() - now.getTime()) / 1e3);
|
|
2278
|
+
if (Math.abs(diffSeconds) < 45) return "just now";
|
|
2279
|
+
const rtf = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
|
|
2280
|
+
for (const { unit, seconds } of RELATIVE_UNITS) {
|
|
2281
|
+
if (Math.abs(diffSeconds) >= seconds) {
|
|
2282
|
+
return rtf.format(Math.round(diffSeconds / seconds), unit);
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
return rtf.format(Math.round(diffSeconds / 60), "minute");
|
|
2286
|
+
}
|
|
2287
|
+
function formatExactDateTime(value) {
|
|
2288
|
+
const date = toDate(value);
|
|
2289
|
+
if (!date) return "—";
|
|
2290
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
2291
|
+
day: "2-digit",
|
|
2292
|
+
month: "short",
|
|
2293
|
+
year: "numeric",
|
|
2294
|
+
hour: "2-digit",
|
|
2295
|
+
minute: "2-digit",
|
|
2296
|
+
second: "2-digit",
|
|
2297
|
+
timeZoneName: "short"
|
|
2298
|
+
}).format(date);
|
|
2299
|
+
}
|
|
2300
|
+
function formatDate(value) {
|
|
2301
|
+
const date = toDate(value);
|
|
2302
|
+
if (!date) return "—";
|
|
2303
|
+
return new Intl.DateTimeFormat(void 0, { day: "2-digit", month: "short", year: "numeric" }).format(date);
|
|
2304
|
+
}
|
|
2305
|
+
function formatNumber(value) {
|
|
2306
|
+
return new Intl.NumberFormat().format(value);
|
|
2307
|
+
}
|
|
2308
|
+
function formatMoney(amount, currencyCode) {
|
|
2309
|
+
const code = currencyCode?.trim().toUpperCase();
|
|
2310
|
+
if (code && /^[A-Z]{3}$/.test(code)) {
|
|
2311
|
+
try {
|
|
2312
|
+
return new Intl.NumberFormat(void 0, { style: "currency", currency: code }).format(amount);
|
|
2313
|
+
} catch {
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
return code ? `${code} ${formatNumber(amount)}` : formatNumber(amount);
|
|
2317
|
+
}
|
|
2318
|
+
const SOURCE_ALIASES = {
|
|
2319
|
+
admin: { kind: "admin", label: "Admin Panel" },
|
|
2320
|
+
admin_panel: { kind: "admin", label: "Admin Panel" },
|
|
2321
|
+
dashboard: { kind: "admin", label: "Admin Panel" },
|
|
2322
|
+
api: { kind: "api", label: "API" },
|
|
2323
|
+
store_api: { kind: "api", label: "Storefront API" },
|
|
2324
|
+
admin_api: { kind: "api", label: "Admin API" },
|
|
2325
|
+
system: { kind: "system", label: "System" },
|
|
2326
|
+
job: { kind: "job", label: "Background Job" },
|
|
2327
|
+
background_job: { kind: "job", label: "Background Job" },
|
|
2328
|
+
scheduled_job: { kind: "job", label: "Background Job" },
|
|
2329
|
+
cron: { kind: "job", label: "Background Job" },
|
|
2330
|
+
workflow: { kind: "workflow", label: "Workflow" },
|
|
2331
|
+
migration: { kind: "system", label: "Migration" }
|
|
2332
|
+
};
|
|
2333
|
+
function describeSource(source) {
|
|
2334
|
+
if (!source || !source.trim()) return { kind: "unknown", label: "Unknown" };
|
|
2335
|
+
const key = source.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
2336
|
+
return SOURCE_ALIASES[key] ?? { kind: "other", label: source.trim() };
|
|
2337
|
+
}
|
|
2338
|
+
function sourceBadgeColor(kind) {
|
|
2339
|
+
switch (kind) {
|
|
2340
|
+
case "admin":
|
|
2341
|
+
return "blue";
|
|
2342
|
+
case "api":
|
|
2343
|
+
return "purple";
|
|
2344
|
+
case "job":
|
|
2345
|
+
case "workflow":
|
|
2346
|
+
return "orange";
|
|
2347
|
+
case "system":
|
|
2348
|
+
return "green";
|
|
2349
|
+
default:
|
|
2350
|
+
return "grey";
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
const CARDS = [
|
|
2354
|
+
{ key: "total", label: "Total deleted", hint: "All records captured since auditing began" },
|
|
2355
|
+
{ key: "today", label: "Today", hint: "Deleted since midnight (your time)" },
|
|
2356
|
+
{ key: "last_7_days", label: "Last 7 days", hint: "Including today" },
|
|
2357
|
+
{ key: "tables_affected", label: "Entity types affected", hint: "Distinct kinds of records deleted" }
|
|
2358
|
+
];
|
|
2359
|
+
const SummaryCards = ({ stats, loading, failed }) => {
|
|
2360
|
+
if (failed && !stats) return null;
|
|
2361
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: CARDS.map((card) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2362
|
+
"div",
|
|
2363
|
+
{
|
|
2364
|
+
className: "flex flex-col gap-1 rounded-lg border border-ui-border-base bg-ui-bg-subtle px-4 py-3",
|
|
2365
|
+
title: card.hint,
|
|
2366
|
+
children: [
|
|
2367
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: card.label }),
|
|
2368
|
+
loading || !stats ? /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-7 w-16" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-2xl font-semibold leading-8 text-ui-fg-base", children: formatNumber(stats[card.key]) })
|
|
2369
|
+
]
|
|
2370
|
+
},
|
|
2371
|
+
card.key
|
|
2372
|
+
)) });
|
|
2373
|
+
};
|
|
2374
|
+
const BASE = "/admin/deleted-records-audit";
|
|
2375
|
+
class AuditApiError extends Error {
|
|
2376
|
+
status;
|
|
2377
|
+
constructor(message, status) {
|
|
2378
|
+
super(message);
|
|
2379
|
+
this.status = status;
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
async function getJson(url, signal) {
|
|
2383
|
+
const response = await fetch(url, { credentials: "include", signal });
|
|
2384
|
+
if (!response.ok) {
|
|
2385
|
+
let message = response.statusText || "Request failed";
|
|
2386
|
+
try {
|
|
2387
|
+
const body = await response.json();
|
|
2388
|
+
if (body && typeof body === "object" && "message" in body && typeof body.message === "string") {
|
|
2389
|
+
message = body.message;
|
|
2703
2390
|
}
|
|
2704
|
-
|
|
2705
|
-
|
|
2391
|
+
} catch {
|
|
2392
|
+
}
|
|
2393
|
+
throw new AuditApiError(message, response.status);
|
|
2394
|
+
}
|
|
2395
|
+
return await response.json();
|
|
2396
|
+
}
|
|
2397
|
+
function fetchAuditList(params, signal) {
|
|
2398
|
+
return getJson(`${BASE}?${params.toString()}`, signal);
|
|
2399
|
+
}
|
|
2400
|
+
async function fetchAuditStats(signal) {
|
|
2401
|
+
const todayStart = /* @__PURE__ */ new Date();
|
|
2402
|
+
todayStart.setHours(0, 0, 0, 0);
|
|
2403
|
+
const params = new URLSearchParams({ today_start: todayStart.toISOString() });
|
|
2404
|
+
const body = await getJson(`${BASE}/stats?${params.toString()}`, signal);
|
|
2405
|
+
return body.stats;
|
|
2406
|
+
}
|
|
2407
|
+
async function fetchAuditDetail(id, signal) {
|
|
2408
|
+
const body = await getJson(`${BASE}/${encodeURIComponent(id)}`, signal);
|
|
2409
|
+
return body.audit;
|
|
2410
|
+
}
|
|
2411
|
+
const LAST_LIST_URL_KEY = "om.deleted-records-audit.last-list-search";
|
|
2412
|
+
const DATE_PRESETS = [
|
|
2413
|
+
{ value: "any", label: "Any time" },
|
|
2414
|
+
{ value: "today", label: "Today" },
|
|
2415
|
+
{ value: "yesterday", label: "Yesterday" },
|
|
2416
|
+
{ value: "7d", label: "Last 7 days" },
|
|
2417
|
+
{ value: "30d", label: "Last 30 days" },
|
|
2418
|
+
{ value: "custom", label: "Custom range" }
|
|
2419
|
+
];
|
|
2420
|
+
const EMPTY_FILTERS = {
|
|
2421
|
+
q: "",
|
|
2422
|
+
entity: "",
|
|
2423
|
+
category: "",
|
|
2424
|
+
date: "any",
|
|
2425
|
+
from: "",
|
|
2426
|
+
to: "",
|
|
2427
|
+
source: "",
|
|
2428
|
+
deletedBy: ""
|
|
2706
2429
|
};
|
|
2707
|
-
const
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
}, [value, delay]);
|
|
2717
|
-
return debouncedValue;
|
|
2430
|
+
const URL_KEYS = {
|
|
2431
|
+
q: "q",
|
|
2432
|
+
entity: "entity",
|
|
2433
|
+
category: "category",
|
|
2434
|
+
date: "date",
|
|
2435
|
+
from: "from",
|
|
2436
|
+
to: "to",
|
|
2437
|
+
source: "source",
|
|
2438
|
+
deletedBy: "deleted_by"
|
|
2718
2439
|
};
|
|
2719
|
-
const
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2440
|
+
const DATE_PRESET_VALUES = new Set(DATE_PRESETS.map((p) => p.value));
|
|
2441
|
+
const DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
2442
|
+
function filtersFromSearchParams(params) {
|
|
2443
|
+
const read = (key) => params.get(URL_KEYS[key])?.trim() ?? "";
|
|
2444
|
+
const date = read("date");
|
|
2445
|
+
const from = read("from");
|
|
2446
|
+
const to = read("to");
|
|
2447
|
+
return {
|
|
2448
|
+
q: read("q"),
|
|
2449
|
+
entity: read("entity"),
|
|
2450
|
+
category: read("category"),
|
|
2451
|
+
date: DATE_PRESET_VALUES.has(date) ? date : "any",
|
|
2452
|
+
from: DAY_PATTERN.test(from) ? from : "",
|
|
2453
|
+
to: DAY_PATTERN.test(to) ? to : "",
|
|
2454
|
+
source: read("source"),
|
|
2455
|
+
deletedBy: read("deletedBy")
|
|
2456
|
+
};
|
|
2457
|
+
}
|
|
2458
|
+
function filtersToSearchParams(filters) {
|
|
2459
|
+
const params = new URLSearchParams();
|
|
2460
|
+
for (const key of Object.keys(URL_KEYS)) {
|
|
2461
|
+
const value = filters[key];
|
|
2462
|
+
if (!value || value === EMPTY_FILTERS[key]) continue;
|
|
2463
|
+
if ((key === "from" || key === "to") && filters.date !== "custom") continue;
|
|
2464
|
+
params.set(URL_KEYS[key], value);
|
|
2723
2465
|
}
|
|
2724
|
-
|
|
2725
|
-
|
|
2466
|
+
return params;
|
|
2467
|
+
}
|
|
2468
|
+
function hasActiveFilters(filters) {
|
|
2469
|
+
return filtersToSearchParams(filters).toString() !== "";
|
|
2470
|
+
}
|
|
2471
|
+
function startOfDay(date) {
|
|
2472
|
+
const d = new Date(date);
|
|
2473
|
+
d.setHours(0, 0, 0, 0);
|
|
2474
|
+
return d;
|
|
2475
|
+
}
|
|
2476
|
+
function endOfDay(date) {
|
|
2477
|
+
const d = new Date(date);
|
|
2478
|
+
d.setHours(23, 59, 59, 999);
|
|
2479
|
+
return d;
|
|
2480
|
+
}
|
|
2481
|
+
function parseDay(day) {
|
|
2482
|
+
if (!DAY_PATTERN.test(day)) return null;
|
|
2483
|
+
const [y, m, d] = day.split("-").map(Number);
|
|
2484
|
+
const date = new Date(y, m - 1, d);
|
|
2485
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
2486
|
+
}
|
|
2487
|
+
function resolveDateRange(filters, now = /* @__PURE__ */ new Date()) {
|
|
2488
|
+
const today = startOfDay(now);
|
|
2489
|
+
switch (filters.date) {
|
|
2490
|
+
case "today":
|
|
2491
|
+
return { from: today };
|
|
2492
|
+
case "yesterday": {
|
|
2493
|
+
const y = new Date(today);
|
|
2494
|
+
y.setDate(y.getDate() - 1);
|
|
2495
|
+
return { from: y, to: endOfDay(y) };
|
|
2496
|
+
}
|
|
2497
|
+
case "7d": {
|
|
2498
|
+
const from = new Date(today);
|
|
2499
|
+
from.setDate(from.getDate() - 6);
|
|
2500
|
+
return { from };
|
|
2501
|
+
}
|
|
2502
|
+
case "30d": {
|
|
2503
|
+
const from = new Date(today);
|
|
2504
|
+
from.setDate(from.getDate() - 29);
|
|
2505
|
+
return { from };
|
|
2506
|
+
}
|
|
2507
|
+
case "custom": {
|
|
2508
|
+
const from = parseDay(filters.from);
|
|
2509
|
+
const to = parseDay(filters.to);
|
|
2510
|
+
return { from: from ?? void 0, to: to ? endOfDay(to) : void 0 };
|
|
2511
|
+
}
|
|
2512
|
+
default:
|
|
2513
|
+
return {};
|
|
2726
2514
|
}
|
|
2727
|
-
|
|
2728
|
-
|
|
2515
|
+
}
|
|
2516
|
+
function filtersToApiParams(filters, page, now = /* @__PURE__ */ new Date()) {
|
|
2517
|
+
const params = new URLSearchParams();
|
|
2518
|
+
params.set("limit", String(page.limit));
|
|
2519
|
+
params.set("offset", String(page.offset));
|
|
2520
|
+
if (filters.q) params.set("q", filters.q);
|
|
2521
|
+
if (filters.entity) {
|
|
2522
|
+
params.set("table_name", filters.entity);
|
|
2523
|
+
} else if (filters.category) {
|
|
2524
|
+
const tables = getTablesForCategory(filters.category);
|
|
2525
|
+
if (tables.length) params.set("table_names", tables.join(","));
|
|
2729
2526
|
}
|
|
2730
|
-
|
|
2731
|
-
|
|
2527
|
+
const range = resolveDateRange(filters, now);
|
|
2528
|
+
if (range.from) params.set("date_from", range.from.toISOString());
|
|
2529
|
+
if (range.to) params.set("date_to", range.to.toISOString());
|
|
2530
|
+
if (filters.source) params.set("source", filters.source);
|
|
2531
|
+
if (filters.deletedBy) params.set("deleted_by", filters.deletedBy);
|
|
2532
|
+
return params;
|
|
2533
|
+
}
|
|
2534
|
+
const PAGE_SIZE = 50;
|
|
2535
|
+
const RESTORE_PAGE_SIZE = 100;
|
|
2536
|
+
const MAX_RESTORE_ROWS = 500;
|
|
2537
|
+
const ALL = "__all__";
|
|
2538
|
+
const UNKNOWN_SOURCE = "unknown";
|
|
2539
|
+
const LOADED_COUNT_KEY_PREFIX = "om.deleted-records-audit.loaded:";
|
|
2540
|
+
const LAST_VIEWED_KEY = "om.deleted-records-audit.last-viewed";
|
|
2541
|
+
function readSession(key) {
|
|
2542
|
+
try {
|
|
2543
|
+
return window.sessionStorage.getItem(key);
|
|
2544
|
+
} catch {
|
|
2545
|
+
return null;
|
|
2732
2546
|
}
|
|
2733
|
-
|
|
2734
|
-
|
|
2547
|
+
}
|
|
2548
|
+
function writeSession(key, value) {
|
|
2549
|
+
try {
|
|
2550
|
+
window.sessionStorage.setItem(key, value);
|
|
2551
|
+
} catch {
|
|
2735
2552
|
}
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
const ReturnsPage = () => {
|
|
2553
|
+
}
|
|
2554
|
+
const DeletedRecordsPage = () => {
|
|
2739
2555
|
const navigate = reactRouterDom.useNavigate();
|
|
2556
|
+
const location = reactRouterDom.useLocation();
|
|
2557
|
+
const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
|
|
2558
|
+
const filters = react.useMemo(() => filtersFromSearchParams(searchParams), [searchParams]);
|
|
2559
|
+
const filterKey = filtersToSearchParams(filters).toString();
|
|
2560
|
+
const filtersActive = hasActiveFilters(filters);
|
|
2561
|
+
const [searchText, setSearchText] = react.useState(filters.q);
|
|
2740
2562
|
const [items, setItems] = react.useState([]);
|
|
2741
|
-
const [
|
|
2742
|
-
const [createdByFilter, setCreatedByFilter] = react.useState("all");
|
|
2743
|
-
const [searchQuery, setSearchQuery] = react.useState("");
|
|
2744
|
-
const debouncedSearchQuery = useDebounce$1(searchQuery, 300);
|
|
2563
|
+
const [count, setCount] = react.useState(0);
|
|
2745
2564
|
const [isLoading, setIsLoading] = react.useState(true);
|
|
2746
2565
|
const [isFetchingMore, setIsFetchingMore] = react.useState(false);
|
|
2747
2566
|
const [error, setError] = react.useState(null);
|
|
2748
|
-
const [
|
|
2749
|
-
const [
|
|
2750
|
-
const
|
|
2751
|
-
const
|
|
2752
|
-
|
|
2567
|
+
const [stats, setStats] = react.useState(null);
|
|
2568
|
+
const [statsLoading, setStatsLoading] = react.useState(true);
|
|
2569
|
+
const [statsFailed, setStatsFailed] = react.useState(false);
|
|
2570
|
+
const [reloadToken, setReloadToken] = react.useState(0);
|
|
2571
|
+
const [highlightId, setHighlightId] = react.useState(null);
|
|
2572
|
+
const restoredScrollRef = react.useRef(false);
|
|
2573
|
+
const updateFilters = react.useCallback(
|
|
2574
|
+
(patch) => {
|
|
2575
|
+
const next = { ...filters, ...patch };
|
|
2576
|
+
setSearchParams(filtersToSearchParams(next), { replace: true });
|
|
2577
|
+
},
|
|
2578
|
+
[filters, setSearchParams]
|
|
2579
|
+
);
|
|
2580
|
+
react.useEffect(() => {
|
|
2581
|
+
if (searchText.trim() === filters.q) return;
|
|
2582
|
+
const handle = setTimeout(() => updateFilters({ q: searchText.trim() }), 300);
|
|
2583
|
+
return () => clearTimeout(handle);
|
|
2584
|
+
}, [searchText, filters.q, updateFilters]);
|
|
2585
|
+
react.useEffect(() => {
|
|
2586
|
+
setSearchText((current) => current.trim() === filters.q ? current : filters.q);
|
|
2587
|
+
}, [filters.q]);
|
|
2588
|
+
react.useEffect(() => {
|
|
2589
|
+
writeSession(LAST_LIST_URL_KEY, location.search);
|
|
2590
|
+
}, [location.search]);
|
|
2591
|
+
const loadStats = react.useCallback(async (signal) => {
|
|
2592
|
+
setStatsLoading(true);
|
|
2593
|
+
setStatsFailed(false);
|
|
2594
|
+
try {
|
|
2595
|
+
setStats(await fetchAuditStats(signal));
|
|
2596
|
+
} catch (e) {
|
|
2597
|
+
if (!signal?.aborted) setStatsFailed(true);
|
|
2598
|
+
} finally {
|
|
2599
|
+
if (!signal?.aborted) setStatsLoading(false);
|
|
2600
|
+
}
|
|
2601
|
+
}, []);
|
|
2602
|
+
react.useEffect(() => {
|
|
2603
|
+
const controller = new AbortController();
|
|
2604
|
+
void loadStats(controller.signal);
|
|
2605
|
+
return () => controller.abort();
|
|
2606
|
+
}, [loadStats, reloadToken]);
|
|
2607
|
+
react.useEffect(() => {
|
|
2608
|
+
const controller = new AbortController();
|
|
2609
|
+
const restoreTarget = Math.min(
|
|
2610
|
+
MAX_RESTORE_ROWS,
|
|
2611
|
+
Math.max(PAGE_SIZE, Number(readSession(LOADED_COUNT_KEY_PREFIX + filterKey)) || 0)
|
|
2612
|
+
);
|
|
2613
|
+
setIsLoading(true);
|
|
2614
|
+
setError(null);
|
|
2615
|
+
(async () => {
|
|
2753
2616
|
try {
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
}
|
|
2766
|
-
if (debouncedSearchQuery.trim()) {
|
|
2767
|
-
params.set("q", debouncedSearchQuery.trim());
|
|
2768
|
-
}
|
|
2769
|
-
if (createdByFilter !== "all") {
|
|
2770
|
-
params.set("created_by", createdByFilter);
|
|
2771
|
-
}
|
|
2772
|
-
params.set("order", "created_at");
|
|
2773
|
-
const response = await fetch(
|
|
2774
|
-
`/admin/return?${params.toString()}`,
|
|
2775
|
-
{ credentials: "include" }
|
|
2776
|
-
);
|
|
2777
|
-
if (!response.ok) {
|
|
2778
|
-
const message = await response.text();
|
|
2779
|
-
throw new Error(message || "Unable to load return orders");
|
|
2617
|
+
const collected = [];
|
|
2618
|
+
let total = 0;
|
|
2619
|
+
while (collected.length < restoreTarget) {
|
|
2620
|
+
const limit = restoreTarget > PAGE_SIZE ? RESTORE_PAGE_SIZE : PAGE_SIZE;
|
|
2621
|
+
const page = await fetchAuditList(
|
|
2622
|
+
filtersToApiParams(filters, { limit, offset: collected.length }),
|
|
2623
|
+
controller.signal
|
|
2624
|
+
);
|
|
2625
|
+
total = page.count;
|
|
2626
|
+
collected.push(...page.audits);
|
|
2627
|
+
if (page.audits.length < limit || collected.length >= total) break;
|
|
2780
2628
|
}
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
);
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
setError(message);
|
|
2629
|
+
if (controller.signal.aborted) return;
|
|
2630
|
+
setItems(collected.slice(0, restoreTarget));
|
|
2631
|
+
setCount(total);
|
|
2632
|
+
} catch (e) {
|
|
2633
|
+
if (controller.signal.aborted) return;
|
|
2634
|
+
setItems([]);
|
|
2635
|
+
setCount(0);
|
|
2636
|
+
setError(e instanceof Error ? e.message : "Unknown error");
|
|
2790
2637
|
} finally {
|
|
2791
|
-
setIsLoading(false);
|
|
2792
|
-
setIsFetchingMore(false);
|
|
2638
|
+
if (!controller.signal.aborted) setIsLoading(false);
|
|
2793
2639
|
}
|
|
2794
|
-
}
|
|
2795
|
-
|
|
2796
|
-
);
|
|
2640
|
+
})();
|
|
2641
|
+
return () => controller.abort();
|
|
2642
|
+
}, [filterKey, reloadToken]);
|
|
2797
2643
|
react.useEffect(() => {
|
|
2798
|
-
|
|
2799
|
-
}, [
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2644
|
+
if (!isLoading) writeSession(LOADED_COUNT_KEY_PREFIX + filterKey, String(items.length));
|
|
2645
|
+
}, [items.length, isLoading, filterKey]);
|
|
2646
|
+
react.useEffect(() => {
|
|
2647
|
+
if (isLoading || restoredScrollRef.current) return;
|
|
2648
|
+
restoredScrollRef.current = true;
|
|
2649
|
+
const lastViewed = readSession(LAST_VIEWED_KEY);
|
|
2650
|
+
if (!lastViewed || !items.some((item) => item.id === lastViewed)) return;
|
|
2651
|
+
setHighlightId(lastViewed);
|
|
2652
|
+
requestAnimationFrame(() => {
|
|
2653
|
+
const visible = Array.from(document.querySelectorAll(`[data-audit-row="${lastViewed}"]`)).find(
|
|
2654
|
+
(el) => el.offsetParent !== null
|
|
2655
|
+
);
|
|
2656
|
+
visible?.scrollIntoView({ block: "center" });
|
|
2657
|
+
});
|
|
2658
|
+
const handle = setTimeout(() => setHighlightId(null), 2500);
|
|
2659
|
+
return () => clearTimeout(handle);
|
|
2660
|
+
}, [isLoading, items]);
|
|
2661
|
+
const loadMore = async () => {
|
|
2662
|
+
setIsFetchingMore(true);
|
|
2663
|
+
try {
|
|
2664
|
+
const page = await fetchAuditList(filtersToApiParams(filters, { limit: PAGE_SIZE, offset: items.length }));
|
|
2665
|
+
setItems((prev) => [...prev, ...page.audits]);
|
|
2666
|
+
setCount(page.count);
|
|
2667
|
+
} catch (e) {
|
|
2668
|
+
setError(e instanceof Error ? e.message : "Unknown error");
|
|
2669
|
+
} finally {
|
|
2670
|
+
setIsFetchingMore(false);
|
|
2671
|
+
}
|
|
2672
|
+
};
|
|
2673
|
+
const openDetail = (id) => {
|
|
2674
|
+
writeSession(LAST_VIEWED_KEY, id);
|
|
2675
|
+
navigate(`/deleted-records-audit/${id}`, { state: { fromList: true } });
|
|
2676
|
+
};
|
|
2677
|
+
const clearFilters = () => {
|
|
2678
|
+
setSearchText("");
|
|
2679
|
+
setSearchParams(filtersToSearchParams(EMPTY_FILTERS), { replace: true });
|
|
2680
|
+
};
|
|
2681
|
+
const refresh = () => setReloadToken((t) => t + 1);
|
|
2682
|
+
const hasMore = items.length < count;
|
|
2683
|
+
const knownSources = stats?.sources ?? [];
|
|
2684
|
+
const knownDeletedBy = stats?.deleted_by ?? [];
|
|
2685
|
+
const attributionMissing = !!stats && stats.total > 0 && knownSources.length === 0 && knownDeletedBy.length === 0;
|
|
2686
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-3 md:p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-4 md:p-6", children: [
|
|
2687
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-start md:justify-between", children: [
|
|
2808
2688
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2809
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
2810
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "
|
|
2689
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Deleted Records" }),
|
|
2690
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Review records that were permanently deleted from the system." })
|
|
2811
2691
|
] }),
|
|
2812
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2692
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { variant: "secondary", size: "small", onClick: refresh, isLoading: isLoading && items.length > 0, children: [
|
|
2693
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ArrowPath, {}),
|
|
2694
|
+
"Refresh"
|
|
2695
|
+
] })
|
|
2813
2696
|
] }),
|
|
2814
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2697
|
+
/* @__PURE__ */ jsxRuntime.jsx(SummaryCards, { stats, loading: statsLoading, failed: statsFailed }),
|
|
2698
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-3", "aria-label": "Search and filters", children: [
|
|
2815
2699
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2816
2700
|
ui.Input,
|
|
2817
2701
|
{
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2702
|
+
type: "search",
|
|
2703
|
+
size: "base",
|
|
2704
|
+
placeholder: "Search by record ID, e.g. order_01J…, prod_…, cus_…",
|
|
2705
|
+
value: searchText,
|
|
2706
|
+
onChange: (e) => setSearchText(e.target.value),
|
|
2707
|
+
"aria-label": "Search by record ID",
|
|
2708
|
+
className: "w-full"
|
|
2822
2709
|
}
|
|
2823
2710
|
),
|
|
2824
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-
|
|
2825
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2826
|
-
|
|
2711
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 md:flex-row md:flex-wrap md:items-center", children: [
|
|
2712
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2713
|
+
EntityPicker,
|
|
2827
2714
|
{
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2715
|
+
entity: filters.entity,
|
|
2716
|
+
category: filters.category,
|
|
2717
|
+
onChange: (next) => updateFilters(next)
|
|
2718
|
+
}
|
|
2719
|
+
),
|
|
2720
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:w-[160px]", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2721
|
+
ui.Select,
|
|
2722
|
+
{
|
|
2723
|
+
size: "small",
|
|
2724
|
+
value: filters.date,
|
|
2725
|
+
onValueChange: (value) => updateFilters({ date: value }),
|
|
2831
2726
|
children: [
|
|
2832
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2833
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2834
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "admin", children: "Admin" })
|
|
2727
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { "aria-label": "Filter by date", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
2728
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: DATE_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: preset.value, children: preset.label }, preset.value)) })
|
|
2835
2729
|
]
|
|
2836
2730
|
}
|
|
2837
|
-
),
|
|
2838
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2839
|
-
|
|
2731
|
+
) }),
|
|
2732
|
+
filters.date === "custom" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2733
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2734
|
+
ui.Input,
|
|
2735
|
+
{
|
|
2736
|
+
type: "date",
|
|
2737
|
+
size: "small",
|
|
2738
|
+
value: filters.from,
|
|
2739
|
+
max: filters.to || void 0,
|
|
2740
|
+
onChange: (e) => updateFilters({ from: e.target.value }),
|
|
2741
|
+
"aria-label": "From date"
|
|
2742
|
+
}
|
|
2743
|
+
),
|
|
2744
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "to" }),
|
|
2745
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2746
|
+
ui.Input,
|
|
2747
|
+
{
|
|
2748
|
+
type: "date",
|
|
2749
|
+
size: "small",
|
|
2750
|
+
value: filters.to,
|
|
2751
|
+
min: filters.from || void 0,
|
|
2752
|
+
onChange: (e) => updateFilters({ to: e.target.value }),
|
|
2753
|
+
"aria-label": "To date"
|
|
2754
|
+
}
|
|
2755
|
+
)
|
|
2756
|
+
] }) : null,
|
|
2757
|
+
knownSources.length > 0 || filters.source ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:w-[170px]", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2758
|
+
ui.Select,
|
|
2840
2759
|
{
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2760
|
+
size: "small",
|
|
2761
|
+
value: filters.source || ALL,
|
|
2762
|
+
onValueChange: (value) => updateFilters({ source: value === ALL ? "" : value }),
|
|
2844
2763
|
children: [
|
|
2845
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2846
|
-
|
|
2764
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { "aria-label": "Filter by source", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
|
|
2765
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
2766
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: ALL, children: "All sources" }),
|
|
2767
|
+
knownSources.map((source) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: source, children: describeSource(source).label }, source)),
|
|
2768
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: UNKNOWN_SOURCE, children: "Unknown" })
|
|
2769
|
+
] })
|
|
2847
2770
|
]
|
|
2848
2771
|
}
|
|
2849
|
-
)
|
|
2772
|
+
) }) : null,
|
|
2773
|
+
knownDeletedBy.length > 0 || filters.deletedBy ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:w-[200px]", children: [
|
|
2774
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2775
|
+
ui.Input,
|
|
2776
|
+
{
|
|
2777
|
+
size: "small",
|
|
2778
|
+
list: "deleted-records-audit-deleted-by",
|
|
2779
|
+
placeholder: "Deleted by (all users)",
|
|
2780
|
+
defaultValue: filters.deletedBy,
|
|
2781
|
+
onBlur: (e) => updateFilters({ deletedBy: e.target.value.trim() }),
|
|
2782
|
+
onKeyDown: (e) => {
|
|
2783
|
+
if (e.key === "Enter") updateFilters({ deletedBy: e.currentTarget.value.trim() });
|
|
2784
|
+
},
|
|
2785
|
+
"aria-label": "Filter by who deleted the record"
|
|
2786
|
+
},
|
|
2787
|
+
filters.deletedBy
|
|
2788
|
+
),
|
|
2789
|
+
/* @__PURE__ */ jsxRuntime.jsx("datalist", { id: "deleted-records-audit-deleted-by", children: knownDeletedBy.map((value) => /* @__PURE__ */ jsxRuntime.jsx("option", { value }, value)) })
|
|
2790
|
+
] }) : null,
|
|
2791
|
+
filtersActive ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: clearFilters, children: "Clear filters" }) : null
|
|
2850
2792
|
] })
|
|
2851
2793
|
] }),
|
|
2852
|
-
|
|
2853
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2854
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2855
|
-
ui.Button,
|
|
2856
|
-
{
|
|
2857
|
-
variant: "secondary",
|
|
2858
|
-
onClick: () => loadReturns(0, true),
|
|
2859
|
-
children: "Try again"
|
|
2860
|
-
}
|
|
2861
|
-
) })
|
|
2794
|
+
attributionMissing ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: [
|
|
2795
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.InformationCircle, { className: "mt-0.5 shrink-0 text-ui-fg-muted" }),
|
|
2796
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Who deleted a record and where the deletion came from are not being recorded yet, so those columns show “Unknown”. Every deleted record is still captured in full." })
|
|
2862
2797
|
] }) : null,
|
|
2863
|
-
isLoading
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
2875
|
-
] }) }),
|
|
2876
|
-
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((returnOrder) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2877
|
-
"tr",
|
|
2878
|
-
{
|
|
2879
|
-
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
2880
|
-
onClick: () => navigate(`/returns/${returnOrder.id}`),
|
|
2881
|
-
children: [
|
|
2882
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: returnOrder.id }) }) }),
|
|
2883
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.order_id }),
|
|
2884
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: returnOrder.customer_email || returnOrder.order_email || "—" }),
|
|
2885
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2886
|
-
ui.Badge,
|
|
2887
|
-
{
|
|
2888
|
-
size: "2xsmall",
|
|
2889
|
-
className: `uppercase ${getStatusBadgeClass$5(returnOrder.status)}`,
|
|
2890
|
-
children: returnOrder.status.replace(/_/g, " ")
|
|
2891
|
-
}
|
|
2892
|
-
) }),
|
|
2893
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: (() => {
|
|
2894
|
-
const calc = returnOrder.refund;
|
|
2895
|
-
if (calc?.is_processed && calc.final_refund_amount != null) {
|
|
2896
|
-
return formatRefundCurrency(
|
|
2897
|
-
calc.final_refund_amount,
|
|
2898
|
-
calc.currency_code || returnOrder.currency_code
|
|
2899
|
-
);
|
|
2900
|
-
}
|
|
2901
|
-
if (calc) {
|
|
2902
|
-
return "Pending";
|
|
2903
|
-
}
|
|
2904
|
-
if (returnOrder.refund_amount == null) {
|
|
2905
|
-
return "—";
|
|
2906
|
-
}
|
|
2907
|
-
return formatRefundCurrency(
|
|
2908
|
-
Number(returnOrder.refund_amount),
|
|
2909
|
-
returnOrder.currency_code
|
|
2910
|
-
);
|
|
2911
|
-
})() }),
|
|
2912
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(returnOrder.created_at).toLocaleDateString("en-US", {
|
|
2913
|
-
year: "numeric",
|
|
2914
|
-
month: "short",
|
|
2915
|
-
day: "numeric",
|
|
2916
|
-
hour: "numeric",
|
|
2917
|
-
minute: "2-digit",
|
|
2918
|
-
hour12: true
|
|
2919
|
-
}) }),
|
|
2920
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2921
|
-
ui.Button,
|
|
2922
|
-
{
|
|
2923
|
-
variant: "transparent",
|
|
2924
|
-
size: "small",
|
|
2925
|
-
onClick: (e) => {
|
|
2926
|
-
e.stopPropagation();
|
|
2927
|
-
navigate(`/app/orders/${returnOrder.order_id}`);
|
|
2928
|
-
},
|
|
2929
|
-
children: "Go to order"
|
|
2930
|
-
}
|
|
2931
|
-
) })
|
|
2932
|
-
]
|
|
2933
|
-
},
|
|
2934
|
-
returnOrder.id
|
|
2935
|
-
)) })
|
|
2936
|
-
] }) }),
|
|
2937
|
-
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2938
|
-
ui.Button,
|
|
2798
|
+
!isLoading && !error && items.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "text-ui-fg-subtle", "aria-live": "polite", children: [
|
|
2799
|
+
"Showing ",
|
|
2800
|
+
formatNumber(items.length),
|
|
2801
|
+
" of ",
|
|
2802
|
+
formatNumber(count),
|
|
2803
|
+
" ",
|
|
2804
|
+
count === 1 ? "record" : "records",
|
|
2805
|
+
filtersActive ? " matching your filters" : ""
|
|
2806
|
+
] }) : null,
|
|
2807
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { onRetry: refresh, detail: error }) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ListSkeleton, {}) : items.length === 0 ? filtersActive ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2808
|
+
EmptyState,
|
|
2939
2809
|
{
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
children: "Load more"
|
|
2810
|
+
title: "No deleted records found",
|
|
2811
|
+
body: "There are no audit records matching your current filters.",
|
|
2812
|
+
action: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: clearFilters, children: "Clear filters" })
|
|
2944
2813
|
}
|
|
2945
|
-
)
|
|
2814
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2815
|
+
EmptyState,
|
|
2816
|
+
{
|
|
2817
|
+
title: "No deleted records yet",
|
|
2818
|
+
body: "Hard-deleted records will appear here automatically when a monitored database record is permanently deleted."
|
|
2819
|
+
}
|
|
2820
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2821
|
+
/* @__PURE__ */ jsxRuntime.jsx(AuditTable, { items, highlightId, onOpen: openDetail }),
|
|
2822
|
+
/* @__PURE__ */ jsxRuntime.jsx(AuditCards, { items, highlightId, onOpen: openDetail })
|
|
2823
|
+
] }),
|
|
2824
|
+
!error && !isLoading && hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", isLoading: isFetchingMore, onClick: loadMore, children: "Load more" }) }) : null
|
|
2946
2825
|
] }) });
|
|
2947
2826
|
};
|
|
2827
|
+
const HEADER_CELL = "px-3 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted";
|
|
2828
|
+
const DeletedWhen = ({ occurredAt }) => /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: formatExactDateTime(occurredAt), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cursor-default text-sm text-ui-fg-base", children: formatRelativeTime(occurredAt) }) });
|
|
2829
|
+
const SourceBadge = ({ source }) => {
|
|
2830
|
+
const info = describeSource(source);
|
|
2831
|
+
if (info.kind === "unknown") {
|
|
2832
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Unknown" });
|
|
2833
|
+
}
|
|
2834
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: sourceBadgeColor(info.kind), className: "shrink-0 whitespace-nowrap", children: info.label });
|
|
2835
|
+
};
|
|
2836
|
+
const AuditTable = ({ items, highlightId, onOpen }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden w-full overflow-hidden rounded-xl border border-ui-border-base md:block", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full table-fixed divide-y divide-ui-border-base", children: [
|
|
2837
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2838
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[22%]"), children: "Entity" }),
|
|
2839
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[24%]"), children: "Record" }),
|
|
2840
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[13%]"), children: "Deleted" }),
|
|
2841
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[13%]"), children: "Deleted by" }),
|
|
2842
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[11%]"), children: "Source" }),
|
|
2843
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[8%]"), children: "Status" }),
|
|
2844
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { className: ui.clx(HEADER_CELL, "w-[9%]"), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Action" }) })
|
|
2845
|
+
] }) }),
|
|
2846
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((item) => {
|
|
2847
|
+
const entity = getEntityInfo(item.table_name);
|
|
2848
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2849
|
+
"tr",
|
|
2850
|
+
{
|
|
2851
|
+
"data-audit-row": item.id,
|
|
2852
|
+
tabIndex: 0,
|
|
2853
|
+
onClick: () => onOpen(item.id),
|
|
2854
|
+
onKeyDown: (e) => {
|
|
2855
|
+
if (e.key === "Enter") onOpen(item.id);
|
|
2856
|
+
},
|
|
2857
|
+
className: ui.clx(
|
|
2858
|
+
"cursor-pointer outline-none transition-colors hover:bg-ui-bg-subtle/60 focus-visible:bg-ui-bg-subtle",
|
|
2859
|
+
highlightId === item.id && "bg-ui-bg-highlight"
|
|
2860
|
+
),
|
|
2861
|
+
children: [
|
|
2862
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
2863
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-ui-fg-base", title: entity.label, children: entity.label }),
|
|
2864
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-ui-fg-muted", children: entity.category.label })
|
|
2865
|
+
] }) }),
|
|
2866
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: item.record_id }) }),
|
|
2867
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(DeletedWhen, { occurredAt: item.occurred_at }) }),
|
|
2868
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 truncate px-3 py-3 text-sm", title: item.deleted_by ?? void 0, children: item.deleted_by ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-base", children: item.deleted_by }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-fg-muted", children: "Unknown" }) }),
|
|
2869
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(SourceBadge, { source: item.source }) }),
|
|
2870
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "min-w-0 px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "red", children: "Deleted" }) }),
|
|
2871
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-3 text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-0.5 whitespace-nowrap text-sm font-medium text-ui-fg-interactive", children: [
|
|
2872
|
+
"View",
|
|
2873
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
2874
|
+
] }) })
|
|
2875
|
+
]
|
|
2876
|
+
},
|
|
2877
|
+
item.id
|
|
2878
|
+
);
|
|
2879
|
+
}) })
|
|
2880
|
+
] }) });
|
|
2881
|
+
const AuditCards = ({ items, highlightId, onOpen }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-2 md:hidden", children: items.map((item) => {
|
|
2882
|
+
const entity = getEntityInfo(item.table_name);
|
|
2883
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { "data-audit-row": item.id, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2884
|
+
"div",
|
|
2885
|
+
{
|
|
2886
|
+
role: "button",
|
|
2887
|
+
tabIndex: 0,
|
|
2888
|
+
onClick: () => onOpen(item.id),
|
|
2889
|
+
onKeyDown: (e) => {
|
|
2890
|
+
if (e.key === "Enter") onOpen(item.id);
|
|
2891
|
+
},
|
|
2892
|
+
className: ui.clx(
|
|
2893
|
+
"flex w-full flex-col gap-2 rounded-lg border border-ui-border-base p-3 text-left outline-none hover:bg-ui-bg-subtle/60 focus-visible:bg-ui-bg-subtle",
|
|
2894
|
+
highlightId === item.id && "bg-ui-bg-highlight"
|
|
2895
|
+
),
|
|
2896
|
+
children: [
|
|
2897
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
2898
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col", children: [
|
|
2899
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-ui-fg-base", children: entity.label }),
|
|
2900
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-ui-fg-muted", children: entity.category.label })
|
|
2901
|
+
] }),
|
|
2902
|
+
/* @__PURE__ */ jsxRuntime.jsx(DeletedWhen, { occurredAt: item.occurred_at })
|
|
2903
|
+
] }),
|
|
2904
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyableId, { value: item.record_id }),
|
|
2905
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2906
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2907
|
+
/* @__PURE__ */ jsxRuntime.jsx(SourceBadge, { source: item.source }),
|
|
2908
|
+
item.deleted_by ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate text-xs text-ui-fg-subtle", children: [
|
|
2909
|
+
"by ",
|
|
2910
|
+
item.deleted_by
|
|
2911
|
+
] }) : null
|
|
2912
|
+
] }),
|
|
2913
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center whitespace-nowrap text-sm font-medium text-ui-fg-interactive", children: [
|
|
2914
|
+
"View details",
|
|
2915
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRightMini, {})
|
|
2916
|
+
] })
|
|
2917
|
+
] })
|
|
2918
|
+
]
|
|
2919
|
+
}
|
|
2920
|
+
) }, item.id);
|
|
2921
|
+
}) });
|
|
2922
|
+
const ListSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0 overflow-hidden rounded-xl border border-ui-border-base", "aria-busy": "true", children: [
|
|
2923
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-ui-bg-subtle px-3 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-40" }) }),
|
|
2924
|
+
Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 border-t border-ui-border-subtle px-3 py-4", children: [
|
|
2925
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-[22%] flex-col gap-1.5", children: [
|
|
2926
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-28" }),
|
|
2927
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3 w-16" })
|
|
2928
|
+
] }),
|
|
2929
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-[20%]" }),
|
|
2930
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-3.5 w-[10%]" }),
|
|
2931
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "hidden h-3.5 w-[10%] md:block" }),
|
|
2932
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "hidden h-5 w-14 rounded-full md:block" })
|
|
2933
|
+
] }, i))
|
|
2934
|
+
] });
|
|
2935
|
+
const EmptyState = ({ title, body, action }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-dashed border-ui-border-strong px-6 py-12 text-center", children: [
|
|
2936
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.MagnifierAlert, { className: "text-ui-fg-muted" }),
|
|
2937
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: title }),
|
|
2938
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: body }),
|
|
2939
|
+
action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: action }) : null
|
|
2940
|
+
] });
|
|
2941
|
+
const ErrorState = ({ onRetry, detail }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-ui-border-base px-6 py-12 text-center", children: [
|
|
2942
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ExclamationCircle, { className: "text-ui-fg-error" }),
|
|
2943
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Unable to load deleted records" }),
|
|
2944
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "max-w-md text-ui-fg-subtle", children: "We couldn’t retrieve the audit records right now. Check your connection and try again." }),
|
|
2945
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "max-w-md font-mono text-ui-fg-muted", children: detail }),
|
|
2946
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", className: "mt-2", onClick: onRetry, children: "Try again" })
|
|
2947
|
+
] });
|
|
2948
2948
|
const config$6 = adminSdk.defineRouteConfig({
|
|
2949
|
-
label: "
|
|
2950
|
-
icon: icons.
|
|
2949
|
+
label: "Deleted Records",
|
|
2950
|
+
icon: icons.Trash
|
|
2951
2951
|
});
|
|
2952
2952
|
const useDebounce = (value, delay) => {
|
|
2953
2953
|
const [debouncedValue, setDebouncedValue] = react.useState(value);
|
|
@@ -3145,38 +3145,347 @@ const SwapsPage = () => {
|
|
|
3145
3145
|
hour: "numeric",
|
|
3146
3146
|
minute: "2-digit",
|
|
3147
3147
|
hour12: true
|
|
3148
|
-
}) }),
|
|
3149
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3148
|
+
}) }),
|
|
3149
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3150
|
+
ui.Button,
|
|
3151
|
+
{
|
|
3152
|
+
variant: "transparent",
|
|
3153
|
+
size: "small",
|
|
3154
|
+
onClick: (e) => {
|
|
3155
|
+
e.stopPropagation();
|
|
3156
|
+
navigate(`/app/orders/${swap.order_id}`);
|
|
3157
|
+
},
|
|
3158
|
+
children: "Go to order"
|
|
3159
|
+
}
|
|
3160
|
+
) })
|
|
3161
|
+
]
|
|
3162
|
+
},
|
|
3163
|
+
swap.id
|
|
3164
|
+
)) })
|
|
3165
|
+
] }) }),
|
|
3166
|
+
hasMore ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3167
|
+
ui.Button,
|
|
3168
|
+
{
|
|
3169
|
+
variant: "secondary",
|
|
3170
|
+
isLoading: isFetchingMore,
|
|
3171
|
+
onClick: () => loadSwaps(offset, false),
|
|
3172
|
+
children: "Load more"
|
|
3173
|
+
}
|
|
3174
|
+
) }) : null
|
|
3175
|
+
] }) });
|
|
3176
|
+
};
|
|
3177
|
+
const config$5 = adminSdk.defineRouteConfig({
|
|
3178
|
+
label: "Exchanges",
|
|
3179
|
+
icon: icons.ArrowPath
|
|
3180
|
+
});
|
|
3181
|
+
const getStatusBadgeClass$3 = (status) => {
|
|
3182
|
+
const s2 = status.toLowerCase();
|
|
3183
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3184
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3185
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3186
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3187
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3188
|
+
};
|
|
3189
|
+
const PaymentDetailPage = () => {
|
|
3190
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3191
|
+
const params = reactRouterDom.useParams();
|
|
3192
|
+
const id = params?.id?.trim();
|
|
3193
|
+
const [detail, setDetail] = react.useState(null);
|
|
3194
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
3195
|
+
const [error, setError] = react.useState(null);
|
|
3196
|
+
react.useEffect(() => {
|
|
3197
|
+
if (!id) {
|
|
3198
|
+
setLoading(false);
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
let cancelled = false;
|
|
3202
|
+
setLoading(true);
|
|
3203
|
+
setError(null);
|
|
3204
|
+
fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
|
|
3205
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
3206
|
+
return res.json();
|
|
3207
|
+
}).then((data) => {
|
|
3208
|
+
if (!cancelled) setDetail(data);
|
|
3209
|
+
}).catch((e) => {
|
|
3210
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3211
|
+
}).finally(() => {
|
|
3212
|
+
if (!cancelled) setLoading(false);
|
|
3213
|
+
});
|
|
3214
|
+
return () => {
|
|
3215
|
+
cancelled = true;
|
|
3216
|
+
};
|
|
3217
|
+
}, [id]);
|
|
3218
|
+
const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
|
|
3219
|
+
const sessionStatusRaw = detail?.session_status ?? "—";
|
|
3220
|
+
const paymentStatusRaw = detail?.payment_id != null ? detail?.payment_status ?? "—" : "—";
|
|
3221
|
+
const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
|
|
3222
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
3223
|
+
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3224
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
|
|
3225
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payment session" }),
|
|
3226
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
|
|
3227
|
+
] }) }),
|
|
3228
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3229
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3230
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
|
|
3231
|
+
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
3232
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3233
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3234
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
|
|
3235
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3236
|
+
ui.Button,
|
|
3237
|
+
{
|
|
3238
|
+
variant: "transparent",
|
|
3239
|
+
size: "small",
|
|
3240
|
+
onClick: () => navigate(`/orders/${detail.order_id}`),
|
|
3241
|
+
children: detail.order_id
|
|
3242
|
+
}
|
|
3243
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "—" }) })
|
|
3244
|
+
] }),
|
|
3245
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3246
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
3247
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: displayAmount })
|
|
3248
|
+
] }),
|
|
3249
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3250
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
3251
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.provider_id })
|
|
3252
|
+
] }),
|
|
3253
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3254
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3255
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3256
|
+
ui.Badge,
|
|
3257
|
+
{
|
|
3258
|
+
size: "2xsmall",
|
|
3259
|
+
className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
|
|
3260
|
+
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
3261
|
+
}
|
|
3262
|
+
) })
|
|
3263
|
+
] }),
|
|
3264
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3265
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
3266
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
3267
|
+
] }),
|
|
3268
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3269
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
3270
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
3271
|
+
] }),
|
|
3272
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3273
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
3274
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
3275
|
+
] }),
|
|
3276
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3277
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
3278
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
3279
|
+
year: "numeric",
|
|
3280
|
+
month: "short",
|
|
3281
|
+
day: "numeric",
|
|
3282
|
+
hour: "numeric",
|
|
3283
|
+
minute: "2-digit",
|
|
3284
|
+
hour12: true
|
|
3285
|
+
}) })
|
|
3286
|
+
] })
|
|
3287
|
+
] }) }),
|
|
3288
|
+
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3289
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
3290
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
|
|
3291
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
|
|
3292
|
+
] }) : null
|
|
3293
|
+
] }) });
|
|
3294
|
+
};
|
|
3295
|
+
const config$4 = adminSdk.defineRouteConfig({
|
|
3296
|
+
label: "Payment details",
|
|
3297
|
+
icon: icons.CreditCard
|
|
3298
|
+
});
|
|
3299
|
+
const getStatusBadgeClass$2 = (status) => {
|
|
3300
|
+
const s2 = status.toLowerCase();
|
|
3301
|
+
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3302
|
+
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3303
|
+
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3304
|
+
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3305
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3306
|
+
};
|
|
3307
|
+
const formatAmount = (value) => {
|
|
3308
|
+
return String(value);
|
|
3309
|
+
};
|
|
3310
|
+
const RefundDetailPage = () => {
|
|
3311
|
+
const navigate = reactRouterDom.useNavigate();
|
|
3312
|
+
const params = reactRouterDom.useParams();
|
|
3313
|
+
const id = params?.id?.trim();
|
|
3314
|
+
const [detail, setDetail] = react.useState(null);
|
|
3315
|
+
const [loading, setLoading] = react.useState(!!id);
|
|
3316
|
+
const [error, setError] = react.useState(null);
|
|
3317
|
+
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
3318
|
+
react.useEffect(() => {
|
|
3319
|
+
if (!id) {
|
|
3320
|
+
setLoading(false);
|
|
3321
|
+
return;
|
|
3322
|
+
}
|
|
3323
|
+
let cancelled = false;
|
|
3324
|
+
setLoading(true);
|
|
3325
|
+
setError(null);
|
|
3326
|
+
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
3327
|
+
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
3328
|
+
return res.json();
|
|
3329
|
+
}).then((data) => {
|
|
3330
|
+
if (!cancelled) setDetail(data);
|
|
3331
|
+
}).catch((e) => {
|
|
3332
|
+
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3333
|
+
}).finally(() => {
|
|
3334
|
+
if (!cancelled) setLoading(false);
|
|
3335
|
+
});
|
|
3336
|
+
return () => {
|
|
3337
|
+
cancelled = true;
|
|
3338
|
+
};
|
|
3339
|
+
}, [id]);
|
|
3340
|
+
const paymentStatus = detail?.payment?.status ?? "—";
|
|
3341
|
+
const hasGatewayData = detail?.payment?.payment_data && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
3342
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
3343
|
+
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3344
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
3345
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
3346
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
3347
|
+
] }) }),
|
|
3348
|
+
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3349
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3350
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
3351
|
+
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
3352
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3353
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
3354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3355
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3356
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
3357
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
3358
|
+
] }),
|
|
3359
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3360
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
3361
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
3362
|
+
] }),
|
|
3363
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3364
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
3365
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
3366
|
+
] }),
|
|
3367
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3368
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
3369
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
3370
|
+
year: "numeric",
|
|
3371
|
+
month: "short",
|
|
3372
|
+
day: "numeric",
|
|
3373
|
+
hour: "numeric",
|
|
3374
|
+
minute: "2-digit",
|
|
3375
|
+
hour12: true
|
|
3376
|
+
}) })
|
|
3377
|
+
] }),
|
|
3378
|
+
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3379
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
3380
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
3381
|
+
] }) : null
|
|
3382
|
+
] })
|
|
3383
|
+
] }),
|
|
3384
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3385
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
3386
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3387
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3388
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
3389
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
3390
|
+
] }),
|
|
3391
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3392
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
3393
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
3394
|
+
] }),
|
|
3395
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3396
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
3397
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
3398
|
+
] }),
|
|
3399
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3400
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
3401
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
3402
|
+
] }),
|
|
3403
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3404
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3405
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3406
|
+
ui.Badge,
|
|
3407
|
+
{
|
|
3408
|
+
size: "2xsmall",
|
|
3409
|
+
className: `uppercase ${getStatusBadgeClass$2(paymentStatus)}`,
|
|
3410
|
+
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
3411
|
+
}
|
|
3412
|
+
) })
|
|
3413
|
+
] }),
|
|
3414
|
+
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3415
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3416
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
3417
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
3418
|
+
] }),
|
|
3419
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3420
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
3421
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
3422
|
+
] }),
|
|
3423
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3424
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
3425
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
3426
|
+
detail.computed.refund_percentage.toFixed(1),
|
|
3427
|
+
"%"
|
|
3428
|
+
] })
|
|
3429
|
+
] })
|
|
3430
|
+
] }) : null
|
|
3431
|
+
] })
|
|
3432
|
+
] }),
|
|
3433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3434
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
3435
|
+
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3436
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3437
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
3438
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3150
3439
|
ui.Button,
|
|
3151
3440
|
{
|
|
3152
3441
|
variant: "transparent",
|
|
3153
3442
|
size: "small",
|
|
3154
|
-
onClick: (
|
|
3155
|
-
|
|
3156
|
-
navigate(`/app/orders/${swap.order_id}`);
|
|
3157
|
-
},
|
|
3158
|
-
children: "Go to order"
|
|
3443
|
+
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
3444
|
+
children: detail.order.order_number ?? detail.order.order_id
|
|
3159
3445
|
}
|
|
3160
3446
|
) })
|
|
3161
|
-
]
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3447
|
+
] }),
|
|
3448
|
+
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3449
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
3450
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
3451
|
+
] }) : null,
|
|
3452
|
+
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3453
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
3454
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
3455
|
+
] }) : null,
|
|
3456
|
+
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3457
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
3458
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
3459
|
+
] }) : null,
|
|
3460
|
+
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3461
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
3462
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
3463
|
+
] }) : null
|
|
3464
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
3465
|
+
] }),
|
|
3466
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
3467
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3468
|
+
"button",
|
|
3469
|
+
{
|
|
3470
|
+
type: "button",
|
|
3471
|
+
className: "flex w-full items-center justify-between text-left",
|
|
3472
|
+
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
3473
|
+
"aria-expanded": gatewayExpanded,
|
|
3474
|
+
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
3475
|
+
children: [
|
|
3476
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
3477
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
3478
|
+
]
|
|
3479
|
+
}
|
|
3480
|
+
),
|
|
3481
|
+
gatewayExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
|
|
3482
|
+
] })
|
|
3483
|
+
] }) : null
|
|
3175
3484
|
] }) });
|
|
3176
3485
|
};
|
|
3177
|
-
const config$
|
|
3178
|
-
label: "
|
|
3179
|
-
icon: icons.
|
|
3486
|
+
const config$3 = adminSdk.defineRouteConfig({
|
|
3487
|
+
label: "Refund details",
|
|
3488
|
+
icon: icons.Receipt
|
|
3180
3489
|
});
|
|
3181
3490
|
const MASKED_VALUE = "••••••••••••";
|
|
3182
3491
|
const SENSITIVE_KEY_PATTERNS = [
|
|
@@ -3919,126 +4228,8 @@ const DetailError = ({
|
|
|
3919
4228
|
!notFound ? /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", size: "small", onClick: onRetry, children: "Try again" }) : null
|
|
3920
4229
|
] })
|
|
3921
4230
|
] });
|
|
3922
|
-
const config$
|
|
3923
|
-
const getStatusBadgeClass$
|
|
3924
|
-
const s2 = status.toLowerCase();
|
|
3925
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
3926
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
3927
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
3928
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
3929
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
3930
|
-
};
|
|
3931
|
-
const PaymentDetailPage = () => {
|
|
3932
|
-
const navigate = reactRouterDom.useNavigate();
|
|
3933
|
-
const params = reactRouterDom.useParams();
|
|
3934
|
-
const id = params?.id?.trim();
|
|
3935
|
-
const [detail, setDetail] = react.useState(null);
|
|
3936
|
-
const [loading, setLoading] = react.useState(!!id);
|
|
3937
|
-
const [error, setError] = react.useState(null);
|
|
3938
|
-
react.useEffect(() => {
|
|
3939
|
-
if (!id) {
|
|
3940
|
-
setLoading(false);
|
|
3941
|
-
return;
|
|
3942
|
-
}
|
|
3943
|
-
let cancelled = false;
|
|
3944
|
-
setLoading(true);
|
|
3945
|
-
setError(null);
|
|
3946
|
-
fetch(`/admin/payment-transactions/${id}`, { credentials: "include" }).then((res) => {
|
|
3947
|
-
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
3948
|
-
return res.json();
|
|
3949
|
-
}).then((data) => {
|
|
3950
|
-
if (!cancelled) setDetail(data);
|
|
3951
|
-
}).catch((e) => {
|
|
3952
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
3953
|
-
}).finally(() => {
|
|
3954
|
-
if (!cancelled) setLoading(false);
|
|
3955
|
-
});
|
|
3956
|
-
return () => {
|
|
3957
|
-
cancelled = true;
|
|
3958
|
-
};
|
|
3959
|
-
}, [id]);
|
|
3960
|
-
const displayStatus = detail ? (detail.payment_id != null && detail.payment_status != null && detail.payment_status !== "" ? detail.payment_status : detail.session_status ?? "") || "—" : "";
|
|
3961
|
-
const sessionStatusRaw = detail?.session_status ?? "—";
|
|
3962
|
-
const paymentStatusRaw = detail?.payment_id != null ? detail?.payment_status ?? "—" : "—";
|
|
3963
|
-
const displayAmount = detail ? `${(detail.currency_code ?? "USD").toUpperCase()} ${Number(detail.amount)}` : "";
|
|
3964
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
3965
|
-
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3966
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/payments"), children: "← Payments" }),
|
|
3967
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Payment session" }),
|
|
3968
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: id ?? "—" })
|
|
3969
|
-
] }) }),
|
|
3970
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
3971
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
3972
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/payments"), children: "Back to list" })
|
|
3973
|
-
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
3974
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6 flex flex-col gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
3975
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3976
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order ID" }),
|
|
3977
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: detail.order_id ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3978
|
-
ui.Button,
|
|
3979
|
-
{
|
|
3980
|
-
variant: "transparent",
|
|
3981
|
-
size: "small",
|
|
3982
|
-
onClick: () => navigate(`/orders/${detail.order_id}`),
|
|
3983
|
-
children: detail.order_id
|
|
3984
|
-
}
|
|
3985
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "—" }) })
|
|
3986
|
-
] }),
|
|
3987
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3988
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
3989
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: displayAmount })
|
|
3990
|
-
] }),
|
|
3991
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3992
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
3993
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.provider_id })
|
|
3994
|
-
] }),
|
|
3995
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3996
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
3997
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3998
|
-
ui.Badge,
|
|
3999
|
-
{
|
|
4000
|
-
size: "2xsmall",
|
|
4001
|
-
className: `uppercase ${getStatusBadgeClass$3(displayStatus)}`,
|
|
4002
|
-
children: displayStatus !== "—" ? displayStatus.replace(/_/g, " ") : "—"
|
|
4003
|
-
}
|
|
4004
|
-
) })
|
|
4005
|
-
] }),
|
|
4006
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4007
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Session status (DB)" }),
|
|
4008
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: sessionStatusRaw })
|
|
4009
|
-
] }),
|
|
4010
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4011
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment status (DB)" }),
|
|
4012
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: paymentStatusRaw })
|
|
4013
|
-
] }),
|
|
4014
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4015
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Finalized" }),
|
|
4016
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment_id != null ? "Yes" : "No" })
|
|
4017
|
-
] }),
|
|
4018
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4019
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created" }),
|
|
4020
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.created_at).toLocaleDateString("en-US", {
|
|
4021
|
-
year: "numeric",
|
|
4022
|
-
month: "short",
|
|
4023
|
-
day: "numeric",
|
|
4024
|
-
hour: "numeric",
|
|
4025
|
-
minute: "2-digit",
|
|
4026
|
-
hour12: true
|
|
4027
|
-
}) })
|
|
4028
|
-
] })
|
|
4029
|
-
] }) }),
|
|
4030
|
-
Object.keys(detail.data ?? {}).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4031
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Provider data" }),
|
|
4032
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.data, null, 2) })
|
|
4033
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-ui-border-base p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No provider data for this session." }) })
|
|
4034
|
-
] }) : null
|
|
4035
|
-
] }) });
|
|
4036
|
-
};
|
|
4037
|
-
const config$3 = adminSdk.defineRouteConfig({
|
|
4038
|
-
label: "Payment details",
|
|
4039
|
-
icon: icons.CreditCard
|
|
4040
|
-
});
|
|
4041
|
-
const getStatusBadgeClass$2 = (status) => {
|
|
4231
|
+
const config$2 = adminSdk.defineRouteConfig({});
|
|
4232
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
4042
4233
|
const statusLower = status.toLowerCase();
|
|
4043
4234
|
if (statusLower === "requested") {
|
|
4044
4235
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -4171,7 +4362,7 @@ const ReturnDetailPage = () => {
|
|
|
4171
4362
|
ui.Badge,
|
|
4172
4363
|
{
|
|
4173
4364
|
size: "small",
|
|
4174
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
4365
|
+
className: `uppercase ${getStatusBadgeClass$1(returnOrder.status)}`,
|
|
4175
4366
|
children: returnOrder.status.replace(/_/g, " ")
|
|
4176
4367
|
}
|
|
4177
4368
|
)
|
|
@@ -4254,7 +4445,7 @@ const ReturnDetailPage = () => {
|
|
|
4254
4445
|
ui.Badge,
|
|
4255
4446
|
{
|
|
4256
4447
|
size: "2xsmall",
|
|
4257
|
-
className: `uppercase ${getStatusBadgeClass$
|
|
4448
|
+
className: `uppercase ${getStatusBadgeClass$1(entry.status)}`,
|
|
4258
4449
|
children: entry.status.replace(/_/g, " ")
|
|
4259
4450
|
}
|
|
4260
4451
|
) }),
|
|
@@ -4316,11 +4507,11 @@ const ReturnDetailPage = () => {
|
|
|
4316
4507
|
updateSuccess && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-success bg-ui-bg-success-subtle p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-success", children: "Action completed successfully" }) })
|
|
4317
4508
|
] }) });
|
|
4318
4509
|
};
|
|
4319
|
-
const config$
|
|
4510
|
+
const config$1 = adminSdk.defineRouteConfig({
|
|
4320
4511
|
label: "Return Order Details",
|
|
4321
4512
|
icon: icons.CheckCircle
|
|
4322
4513
|
});
|
|
4323
|
-
const getStatusBadgeClass
|
|
4514
|
+
const getStatusBadgeClass = (status) => {
|
|
4324
4515
|
const statusLower = status.toLowerCase();
|
|
4325
4516
|
if (statusLower === "requested") {
|
|
4326
4517
|
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
@@ -4457,7 +4648,7 @@ const SwapDetailPage = () => {
|
|
|
4457
4648
|
ui.Badge,
|
|
4458
4649
|
{
|
|
4459
4650
|
size: "small",
|
|
4460
|
-
className: `uppercase ${getStatusBadgeClass
|
|
4651
|
+
className: `uppercase ${getStatusBadgeClass(swap.status)}`,
|
|
4461
4652
|
children: swap.status.replace(/_/g, " ")
|
|
4462
4653
|
}
|
|
4463
4654
|
)
|
|
@@ -4525,7 +4716,7 @@ const SwapDetailPage = () => {
|
|
|
4525
4716
|
ui.Badge,
|
|
4526
4717
|
{
|
|
4527
4718
|
size: "2xsmall",
|
|
4528
|
-
className: `uppercase ${getStatusBadgeClass
|
|
4719
|
+
className: `uppercase ${getStatusBadgeClass(entry.status)}`,
|
|
4529
4720
|
children: entry.status.replace(/_/g, " ")
|
|
4530
4721
|
}
|
|
4531
4722
|
) }),
|
|
@@ -4594,201 +4785,10 @@ const SwapDetailPage = () => {
|
|
|
4594
4785
|
] })
|
|
4595
4786
|
] }) });
|
|
4596
4787
|
};
|
|
4597
|
-
const config
|
|
4788
|
+
const config = adminSdk.defineRouteConfig({
|
|
4598
4789
|
label: "Swap Details",
|
|
4599
4790
|
icon: icons.ArrowPath
|
|
4600
4791
|
});
|
|
4601
|
-
const getStatusBadgeClass = (status) => {
|
|
4602
|
-
const s2 = status.toLowerCase();
|
|
4603
|
-
if (s2 === "captured" || s2 === "completed") return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
4604
|
-
if (s2 === "authorized") return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
4605
|
-
if (s2 === "error" || s2 === "canceled" || s2 === "cancelled") return "bg-ui-tag-red-bg text-ui-tag-red-text";
|
|
4606
|
-
if (s2 === "pending" || s2 === "requires_more") return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
4607
|
-
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
4608
|
-
};
|
|
4609
|
-
const formatAmount = (value) => {
|
|
4610
|
-
return String(value);
|
|
4611
|
-
};
|
|
4612
|
-
const RefundDetailPage = () => {
|
|
4613
|
-
const navigate = reactRouterDom.useNavigate();
|
|
4614
|
-
const params = reactRouterDom.useParams();
|
|
4615
|
-
const id = params?.id?.trim();
|
|
4616
|
-
const [detail, setDetail] = react.useState(null);
|
|
4617
|
-
const [loading, setLoading] = react.useState(!!id);
|
|
4618
|
-
const [error, setError] = react.useState(null);
|
|
4619
|
-
const [gatewayExpanded, setGatewayExpanded] = react.useState(false);
|
|
4620
|
-
react.useEffect(() => {
|
|
4621
|
-
if (!id) {
|
|
4622
|
-
setLoading(false);
|
|
4623
|
-
return;
|
|
4624
|
-
}
|
|
4625
|
-
let cancelled = false;
|
|
4626
|
-
setLoading(true);
|
|
4627
|
-
setError(null);
|
|
4628
|
-
fetch(`/admin/refunds/${id}`, { credentials: "include" }).then((res) => {
|
|
4629
|
-
if (!res.ok) throw new Error(res.statusText || "Failed to load");
|
|
4630
|
-
return res.json();
|
|
4631
|
-
}).then((data) => {
|
|
4632
|
-
if (!cancelled) setDetail(data);
|
|
4633
|
-
}).catch((e) => {
|
|
4634
|
-
if (!cancelled) setError(e instanceof Error ? e.message : "Failed to load");
|
|
4635
|
-
}).finally(() => {
|
|
4636
|
-
if (!cancelled) setLoading(false);
|
|
4637
|
-
});
|
|
4638
|
-
return () => {
|
|
4639
|
-
cancelled = true;
|
|
4640
|
-
};
|
|
4641
|
-
}, [id]);
|
|
4642
|
-
const paymentStatus = detail?.payment?.status ?? "—";
|
|
4643
|
-
const hasGatewayData = detail?.payment?.payment_data && typeof detail.payment.payment_data === "object" && Object.keys(detail.payment.payment_data).length > 0;
|
|
4644
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mx-auto flex w-full max-w-4xl flex-col gap-6 p-6", children: [
|
|
4645
|
-
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4646
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "transparent", size: "small", onClick: () => navigate("/refunds"), children: "← Refunds" }),
|
|
4647
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Refund details" }),
|
|
4648
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle font-mono", children: id ?? "—" })
|
|
4649
|
-
] }) }),
|
|
4650
|
-
error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
4651
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
4652
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", className: "mt-4", onClick: () => navigate("/refunds"), children: "Back to list" })
|
|
4653
|
-
] }) : loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Loading…" }) }) : detail ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
4654
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4655
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Refund summary" }),
|
|
4656
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4657
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4658
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund ID" }),
|
|
4659
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.id })
|
|
4660
|
-
] }),
|
|
4661
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4662
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Amount" }),
|
|
4663
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.refund.amount) })
|
|
4664
|
-
] }),
|
|
4665
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4666
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Note" }),
|
|
4667
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.refund.note ?? "—" })
|
|
4668
|
-
] }),
|
|
4669
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4670
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created at" }),
|
|
4671
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: new Date(detail.refund.created_at).toLocaleDateString("en-US", {
|
|
4672
|
-
year: "numeric",
|
|
4673
|
-
month: "short",
|
|
4674
|
-
day: "numeric",
|
|
4675
|
-
hour: "numeric",
|
|
4676
|
-
minute: "2-digit",
|
|
4677
|
-
hour12: true
|
|
4678
|
-
}) })
|
|
4679
|
-
] }),
|
|
4680
|
-
detail.refund.created_by ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4681
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Created by" }),
|
|
4682
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.refund.created_by })
|
|
4683
|
-
] }) : null
|
|
4684
|
-
] })
|
|
4685
|
-
] }),
|
|
4686
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4687
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Payment summary" }),
|
|
4688
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4689
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4690
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Payment amount" }),
|
|
4691
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.payment_amount) })
|
|
4692
|
-
] }),
|
|
4693
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4694
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Captured amount" }),
|
|
4695
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.captured_amount) })
|
|
4696
|
-
] }),
|
|
4697
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4698
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refunded amount" }),
|
|
4699
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.payment.refunded_amount) })
|
|
4700
|
-
] }),
|
|
4701
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4702
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Provider" }),
|
|
4703
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.payment.provider_id || "—" })
|
|
4704
|
-
] }),
|
|
4705
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4706
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Status" }),
|
|
4707
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4708
|
-
ui.Badge,
|
|
4709
|
-
{
|
|
4710
|
-
size: "2xsmall",
|
|
4711
|
-
className: `uppercase ${getStatusBadgeClass(paymentStatus)}`,
|
|
4712
|
-
children: paymentStatus !== "—" ? paymentStatus.replace(/_/g, " ") : "—"
|
|
4713
|
-
}
|
|
4714
|
-
) })
|
|
4715
|
-
] }),
|
|
4716
|
-
detail.computed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4717
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4718
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Full refund" }),
|
|
4719
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.computed.is_full_refund ? "Yes" : "No" })
|
|
4720
|
-
] }),
|
|
4721
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4722
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Remaining refundable" }),
|
|
4723
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.computed.remaining_refundable_amount) })
|
|
4724
|
-
] }),
|
|
4725
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4726
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Refund %" }),
|
|
4727
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mt-1 block", children: [
|
|
4728
|
-
detail.computed.refund_percentage.toFixed(1),
|
|
4729
|
-
"%"
|
|
4730
|
-
] })
|
|
4731
|
-
] })
|
|
4732
|
-
] }) : null
|
|
4733
|
-
] })
|
|
4734
|
-
] }),
|
|
4735
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4736
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg mb-4", children: "Order summary" }),
|
|
4737
|
-
detail.order ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
|
|
4738
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4739
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Order" }),
|
|
4740
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4741
|
-
ui.Button,
|
|
4742
|
-
{
|
|
4743
|
-
variant: "transparent",
|
|
4744
|
-
size: "small",
|
|
4745
|
-
onClick: () => navigate(`/orders/${detail.order.order_id}`),
|
|
4746
|
-
children: detail.order.order_number ?? detail.order.order_id
|
|
4747
|
-
}
|
|
4748
|
-
) })
|
|
4749
|
-
] }),
|
|
4750
|
-
detail.order.total != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4751
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Total" }),
|
|
4752
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: formatAmount(detail.order.total) })
|
|
4753
|
-
] }) : null,
|
|
4754
|
-
detail.order.customer_id ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4755
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Customer ID" }),
|
|
4756
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block font-mono text-sm", children: detail.order.customer_id })
|
|
4757
|
-
] }) : null,
|
|
4758
|
-
detail.order.region ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4759
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Region" }),
|
|
4760
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.region })
|
|
4761
|
-
] }) : null,
|
|
4762
|
-
detail.order.fulfillment_status ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4763
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "Fulfillment status" }),
|
|
4764
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-1 block", children: detail.order.fulfillment_status })
|
|
4765
|
-
] }) : null
|
|
4766
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No order linked to this refund." })
|
|
4767
|
-
] }),
|
|
4768
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-ui-border-base p-6", children: [
|
|
4769
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4770
|
-
"button",
|
|
4771
|
-
{
|
|
4772
|
-
type: "button",
|
|
4773
|
-
className: "flex w-full items-center justify-between text-left",
|
|
4774
|
-
onClick: () => setGatewayExpanded((prev) => !prev),
|
|
4775
|
-
"aria-expanded": gatewayExpanded,
|
|
4776
|
-
"aria-label": gatewayExpanded ? "Collapse gateway data" : "Expand gateway data",
|
|
4777
|
-
children: [
|
|
4778
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-lg", children: "Gateway data" }),
|
|
4779
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: gatewayExpanded ? "Collapse" : "Expand" })
|
|
4780
|
-
]
|
|
4781
|
-
}
|
|
4782
|
-
),
|
|
4783
|
-
gatewayExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: hasGatewayData ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs bg-ui-bg-subtle p-4 rounded-lg overflow-auto max-h-96", children: JSON.stringify(detail.payment.payment_data, null, 2) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: "No gateway payload for this payment." }) })
|
|
4784
|
-
] })
|
|
4785
|
-
] }) : null
|
|
4786
|
-
] }) });
|
|
4787
|
-
};
|
|
4788
|
-
const config = adminSdk.defineRouteConfig({
|
|
4789
|
-
label: "Refund details",
|
|
4790
|
-
icon: icons.Receipt
|
|
4791
|
-
});
|
|
4792
4792
|
const i18nTranslations0 = {};
|
|
4793
4793
|
const widgetModule = { widgets: [
|
|
4794
4794
|
{
|
|
@@ -4804,24 +4804,24 @@ const widgetModule = { widgets: [
|
|
|
4804
4804
|
] };
|
|
4805
4805
|
const routeModule = {
|
|
4806
4806
|
routes: [
|
|
4807
|
-
{
|
|
4808
|
-
Component: DeletedRecordsPage,
|
|
4809
|
-
path: "/deleted-records-audit",
|
|
4810
|
-
handle: { label: config$9.label, translationNs: config$9.translationNs }
|
|
4811
|
-
},
|
|
4812
4807
|
{
|
|
4813
4808
|
Component: PaymentsPage,
|
|
4814
4809
|
path: "/payments",
|
|
4815
|
-
handle: { label: config$
|
|
4810
|
+
handle: { label: config$9.label, translationNs: config$9.translationNs }
|
|
4816
4811
|
},
|
|
4817
4812
|
{
|
|
4818
4813
|
Component: RefundsPage,
|
|
4819
4814
|
path: "/refunds",
|
|
4820
|
-
handle: { label: config$
|
|
4815
|
+
handle: { label: config$8.label, translationNs: config$8.translationNs }
|
|
4821
4816
|
},
|
|
4822
4817
|
{
|
|
4823
4818
|
Component: ReturnsPage,
|
|
4824
4819
|
path: "/returns",
|
|
4820
|
+
handle: { label: config$7.label, translationNs: config$7.translationNs }
|
|
4821
|
+
},
|
|
4822
|
+
{
|
|
4823
|
+
Component: DeletedRecordsPage,
|
|
4824
|
+
path: "/deleted-records-audit",
|
|
4825
4825
|
handle: { label: config$6.label, translationNs: config$6.translationNs }
|
|
4826
4826
|
},
|
|
4827
4827
|
{
|
|
@@ -4830,28 +4830,28 @@ const routeModule = {
|
|
|
4830
4830
|
handle: { label: config$5.label, translationNs: config$5.translationNs }
|
|
4831
4831
|
},
|
|
4832
4832
|
{
|
|
4833
|
-
Component:
|
|
4834
|
-
path: "/
|
|
4833
|
+
Component: PaymentDetailPage,
|
|
4834
|
+
path: "/payments/:id",
|
|
4835
4835
|
handle: { label: config$4.label, translationNs: config$4.translationNs }
|
|
4836
4836
|
},
|
|
4837
4837
|
{
|
|
4838
|
-
Component:
|
|
4839
|
-
path: "/
|
|
4838
|
+
Component: RefundDetailPage,
|
|
4839
|
+
path: "/refunds/:id",
|
|
4840
4840
|
handle: { label: config$3.label, translationNs: config$3.translationNs }
|
|
4841
4841
|
},
|
|
4842
4842
|
{
|
|
4843
|
-
Component:
|
|
4844
|
-
path: "/
|
|
4843
|
+
Component: DeletedRecordDetailPage,
|
|
4844
|
+
path: "/deleted-records-audit/:id",
|
|
4845
4845
|
handle: { label: config$2.label, translationNs: config$2.translationNs }
|
|
4846
4846
|
},
|
|
4847
4847
|
{
|
|
4848
|
-
Component:
|
|
4849
|
-
path: "/
|
|
4848
|
+
Component: ReturnDetailPage,
|
|
4849
|
+
path: "/returns/:id",
|
|
4850
4850
|
handle: { label: config$1.label, translationNs: config$1.translationNs }
|
|
4851
4851
|
},
|
|
4852
4852
|
{
|
|
4853
|
-
Component:
|
|
4854
|
-
path: "/
|
|
4853
|
+
Component: SwapDetailPage,
|
|
4854
|
+
path: "/swaps/:id",
|
|
4855
4855
|
handle: { label: config.label, translationNs: config.translationNs }
|
|
4856
4856
|
}
|
|
4857
4857
|
]
|
|
@@ -4859,32 +4859,32 @@ const routeModule = {
|
|
|
4859
4859
|
const menuItemModule = {
|
|
4860
4860
|
menuItems: [
|
|
4861
4861
|
{
|
|
4862
|
-
label: config$
|
|
4863
|
-
icon: config$
|
|
4862
|
+
label: config$6.label,
|
|
4863
|
+
icon: config$6.icon,
|
|
4864
4864
|
path: "/deleted-records-audit",
|
|
4865
4865
|
nested: void 0,
|
|
4866
4866
|
rank: void 0,
|
|
4867
4867
|
translationNs: void 0
|
|
4868
4868
|
},
|
|
4869
4869
|
{
|
|
4870
|
-
label: config$
|
|
4871
|
-
icon: config$
|
|
4870
|
+
label: config$9.label,
|
|
4871
|
+
icon: config$9.icon,
|
|
4872
4872
|
path: "/payments",
|
|
4873
4873
|
nested: void 0,
|
|
4874
4874
|
rank: void 0,
|
|
4875
4875
|
translationNs: void 0
|
|
4876
4876
|
},
|
|
4877
4877
|
{
|
|
4878
|
-
label: config$
|
|
4879
|
-
icon: config$
|
|
4878
|
+
label: config$8.label,
|
|
4879
|
+
icon: config$8.icon,
|
|
4880
4880
|
path: "/refunds",
|
|
4881
4881
|
nested: void 0,
|
|
4882
4882
|
rank: void 0,
|
|
4883
4883
|
translationNs: void 0
|
|
4884
4884
|
},
|
|
4885
4885
|
{
|
|
4886
|
-
label: config$
|
|
4887
|
-
icon: config$
|
|
4886
|
+
label: config$7.label,
|
|
4887
|
+
icon: config$7.icon,
|
|
4888
4888
|
path: "/returns",
|
|
4889
4889
|
nested: void 0,
|
|
4890
4890
|
rank: void 0,
|
|
@@ -4899,32 +4899,32 @@ const menuItemModule = {
|
|
|
4899
4899
|
translationNs: void 0
|
|
4900
4900
|
},
|
|
4901
4901
|
{
|
|
4902
|
-
label: config$
|
|
4903
|
-
icon: config$
|
|
4902
|
+
label: config$4.label,
|
|
4903
|
+
icon: config$4.icon,
|
|
4904
4904
|
path: "/payments/:id",
|
|
4905
4905
|
nested: void 0,
|
|
4906
4906
|
rank: void 0,
|
|
4907
4907
|
translationNs: void 0
|
|
4908
4908
|
},
|
|
4909
4909
|
{
|
|
4910
|
-
label: config.label,
|
|
4911
|
-
icon: config.icon,
|
|
4910
|
+
label: config$3.label,
|
|
4911
|
+
icon: config$3.icon,
|
|
4912
4912
|
path: "/refunds/:id",
|
|
4913
4913
|
nested: void 0,
|
|
4914
4914
|
rank: void 0,
|
|
4915
4915
|
translationNs: void 0
|
|
4916
4916
|
},
|
|
4917
4917
|
{
|
|
4918
|
-
label: config$
|
|
4919
|
-
icon: config$
|
|
4918
|
+
label: config$1.label,
|
|
4919
|
+
icon: config$1.icon,
|
|
4920
4920
|
path: "/returns/:id",
|
|
4921
4921
|
nested: void 0,
|
|
4922
4922
|
rank: void 0,
|
|
4923
4923
|
translationNs: void 0
|
|
4924
4924
|
},
|
|
4925
4925
|
{
|
|
4926
|
-
label: config
|
|
4927
|
-
icon: config
|
|
4926
|
+
label: config.label,
|
|
4927
|
+
icon: config.icon,
|
|
4928
4928
|
path: "/swaps/:id",
|
|
4929
4929
|
nested: void 0,
|
|
4930
4930
|
rank: void 0,
|