@mohasinac/appkit 4.41.16 → 4.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +1 -1
- package/dist/_internal/server/features/checkout/actions.d.ts +16 -14
- package/dist/_internal/server/features/checkout/actions.js +145 -97
- package/dist/_internal/server/features/checkout/bundle-expansion.d.ts +1 -1
- package/dist/_internal/server/features/checkout/index.d.ts +1 -1
- package/dist/_internal/server/features/checkout/index.js +1 -1
- package/dist/_internal/server/features/checkout/locked-lines.js +1 -1
- package/dist/_internal/server/features/checkout/source-context.js +2 -2
- package/dist/_internal/server/features/maintenance/analyze.js +1 -1
- package/dist/_internal/server/features/refunds/actions.d.ts +4 -4
- package/dist/_internal/server/features/refunds/actions.js +9 -8
- package/dist/_internal/server/functions/scheduled.d.ts +1 -2
- package/dist/_internal/server/functions/scheduled.js +1 -9
- package/dist/_internal/server/jobs/core/index.d.ts +0 -1
- package/dist/_internal/server/jobs/core/index.js +0 -1
- package/dist/_internal/server/jobs/handlers/index.d.ts +0 -1
- package/dist/_internal/server/jobs/handlers/index.js +0 -1
- package/dist/_internal/shared/actions/action-registry.js +2 -2
- package/dist/_internal/shared/checkout/order-math.d.ts +1 -1
- package/dist/_internal/shared/checkout/order-math.js +1 -1
- package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +2 -2
- package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
- package/dist/_internal/shared/features/cart/schema.d.ts +6 -6
- package/dist/_internal/shared/features/orders/refund-copy.d.ts +1 -1
- package/dist/_internal/shared/features/orders/refund-copy.js +1 -1
- package/dist/_internal/shared/features/orders/schema.d.ts +5 -5
- package/dist/_internal/shared/features/orders/schema.js +1 -1
- package/dist/_internal/shared/features/products/schema.d.ts +2 -2
- package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
- package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/configs/next.js +2 -2
- package/dist/constants/field-names.d.ts +1 -1
- package/dist/constants/field-names.js +1 -1
- package/dist/contracts/index.d.ts +0 -2
- package/dist/contracts/index.js +0 -1
- package/dist/contracts/payment.d.ts +13 -2
- package/dist/contracts/payment.js +2 -2
- package/dist/core/integration-keys.d.ts +7 -3
- package/dist/core/integration-keys.js +13 -7
- package/dist/core/money.d.ts +11 -0
- package/dist/core/money.js +15 -0
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/messages.d.ts +1 -0
- package/dist/errors/messages.js +1 -0
- package/dist/errors/{razorpay-unreachable.d.ts → payment-provider-unreachable.d.ts} +1 -1
- package/dist/errors/{razorpay-unreachable.js → payment-provider-unreachable.js} +1 -1
- package/dist/features/addresses/schemas/address-form.d.ts +20 -20
- package/dist/features/addresses/schemas/index.d.ts +2 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +32 -16
- package/dist/features/admin/constants/site-settings-tabs.d.ts +1 -1
- package/dist/features/admin/schemas/admin-ops-forms.d.ts +10 -10
- package/dist/features/admin/schemas/admin-user-form.d.ts +2 -2
- package/dist/features/admin/schemas/firestore.d.ts +17 -8
- package/dist/features/admin/schemas/firestore.js +1 -1
- package/dist/features/admin/schemas/nav-item-form.d.ts +2 -2
- package/dist/features/auctions/schemas/index.d.ts +2 -2
- package/dist/features/auth/schemas/index.d.ts +2 -2
- package/dist/features/before-after/schemas/index.d.ts +2 -2
- package/dist/features/blog/actions/blog-actions.d.ts +4 -4
- package/dist/features/blog/schemas/blog-form.d.ts +2 -2
- package/dist/features/blog/schemas/index.d.ts +4 -4
- package/dist/features/cart/schemas/index.d.ts +3 -3
- package/dist/features/catalogue/schemas/validation.d.ts +4 -4
- package/dist/features/categories/schemas/index.d.ts +2 -2
- package/dist/features/checkout/index.d.ts +0 -4
- package/dist/features/checkout/index.js +0 -3
- package/dist/features/checkout/types/index.d.ts +0 -25
- package/dist/features/checkout/types/index.js +1 -2
- package/dist/features/collections/schemas/index.d.ts +2 -2
- package/dist/features/consultation/schemas/index.d.ts +4 -4
- package/dist/features/corporate/schemas/index.d.ts +2 -2
- package/dist/features/events/schemas/index.d.ts +4 -4
- package/dist/features/grouped/schemas/index.d.ts +2 -2
- package/dist/features/homepage/schemas/index.d.ts +2 -2
- package/dist/features/lottery/schemas/zod.d.ts +4 -4
- package/dist/features/loyalty/schemas/index.d.ts +6 -6
- package/dist/features/orders/components/OrderPaymentSummary.d.ts +1 -1
- package/dist/features/orders/components/OrderPaymentSummary.js +5 -5
- package/dist/features/orders/components/RefundHistoryTable.js +1 -1
- package/dist/features/orders/repository/orders.repository.d.ts +10 -1
- package/dist/features/orders/repository/orders.repository.js +17 -1
- package/dist/features/orders/schemas/firestore.d.ts +11 -12
- package/dist/features/orders/schemas/firestore.js +0 -1
- package/dist/features/orders/schemas/index.d.ts +48 -48
- package/dist/features/orders/schemas/index.js +1 -1
- package/dist/features/orders/types/index.d.ts +1 -3
- package/dist/features/orders/types/index.js +1 -2
- package/dist/features/payments/manifest.js +1 -1
- package/dist/features/payments/repository/payout.repository.d.ts +1 -4
- package/dist/features/payments/repository/payout.repository.js +0 -29
- package/dist/features/payments/schemas/firestore.d.ts +8 -15
- package/dist/features/payments/schemas/firestore.js +7 -5
- package/dist/features/payments/schemas/index.d.ts +52 -125
- package/dist/features/payments/schemas/index.js +0 -58
- package/dist/features/payments/types/index.d.ts +2 -4
- package/dist/features/payments/types/index.js +1 -2
- package/dist/features/products/schemas/index.d.ts +14 -14
- package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
- package/dist/features/promotions/schemas/index.d.ts +20 -20
- package/dist/features/reviews/schemas/index.d.ts +8 -8
- package/dist/features/scams/schemas/index.d.ts +10 -10
- package/dist/features/search/action-index/settings-entries.js +4 -4
- package/dist/features/seller/schemas/index.d.ts +12 -12
- package/dist/features/seller/schemas/order-forms.d.ts +4 -4
- package/dist/features/shipments/schemas/validation.d.ts +28 -28
- package/dist/features/store-extensions/schemas/payout-method-form.d.ts +50 -50
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +2 -2
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +10 -10
- package/dist/features/support/schemas/index.d.ts +14 -14
- package/dist/features/tester/actions/checklist-item-actions.d.ts +4 -4
- package/dist/features/tester/schemas/checklist-item-form.d.ts +2 -2
- package/dist/features/tester/seed-data/_money-flows.js +145 -0
- package/dist/features/tester/seed-data/authored/account-auth__signup-login.js +21 -2
- package/dist/features/tester/seed-data/authored/admin__site-system.js +38 -0
- package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +10 -10
- package/dist/features/tester/seed-data/authored/buying__offers.js +11 -10
- package/dist/features/tester/seed-data/authored/cta-layout__checkout-bottom-bar.js +1 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +24 -12
- package/dist/features/wishlist/schemas/index.d.ts +2 -2
- package/dist/index.d.ts +6 -28
- package/dist/index.js +8 -51
- package/dist/jobs.d.ts +1 -1
- package/dist/jobs.js +1 -1
- package/dist/providers/payment-phonepe/index.d.ts +117 -0
- package/dist/providers/payment-phonepe/index.js +221 -0
- package/dist/providers.d.ts +3 -2
- package/dist/providers.js +3 -2
- package/dist/schemas/registry.d.ts +163 -2623
- package/dist/schemas/registry.js +1 -6
- package/dist/seed/faq-seed-data.js +5 -5
- package/dist/seed/payouts-seed-data.js +3 -3
- package/dist/seed/site-settings-seed-data.js +7 -4
- package/dist/server-entry.d.ts +1 -2
- package/dist/server-entry.js +1 -3
- package/dist/server.d.ts +3 -9
- package/dist/server.js +5 -23
- package/dist/validation/schemas.d.ts +2 -2
- package/package.json +5 -4
- package/dist/_internal/server/features/payments/actions.d.ts +0 -30
- package/dist/_internal/server/features/payments/actions.js +0 -45
- package/dist/_internal/server/features/payments/data.d.ts +0 -13
- package/dist/_internal/server/features/payments/data.js +0 -20
- package/dist/_internal/server/features/payments/index.d.ts +0 -3
- package/dist/_internal/server/features/payments/index.js +0 -3
- package/dist/_internal/server/jobs/core/payoutBatch.d.ts +0 -2
- package/dist/_internal/server/jobs/core/payoutBatch.js +0 -120
- package/dist/_internal/server/jobs/handlers/payoutBatch.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/payoutBatch.js +0 -2
- package/dist/_internal/shared/features/payments/config.d.ts +0 -3
- package/dist/_internal/shared/features/payments/config.js +0 -3
- package/dist/contracts/client-payment-gateway.d.ts +0 -64
- package/dist/contracts/client-payment-gateway.js +0 -25
- package/dist/features/checkout/hooks/useCheckout.d.ts +0 -9
- package/dist/features/checkout/hooks/useCheckout.js +0 -24
- package/dist/features/checkout/hooks/useCheckoutApi.d.ts +0 -72
- package/dist/features/checkout/hooks/useCheckoutApi.js +0 -47
- package/dist/features/checkout/hooks/usePaymentCheckout.d.ts +0 -77
- package/dist/features/checkout/hooks/usePaymentCheckout.js +0 -192
- package/dist/providers/payment-razorpay/index.d.ts +0 -115
- package/dist/providers/payment-razorpay/index.js +0 -208
- package/dist/schemas/webhooks/razorpay.d.ts +0 -2634
- package/dist/schemas/webhooks/razorpay.js +0 -104
|
@@ -11,14 +11,17 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Usage:
|
|
13
13
|
* const keys = await resolveKeys();
|
|
14
|
-
* const
|
|
14
|
+
* const client = StandardCheckoutClient.getInstance(keys.phonepeClientId, keys.phonepeClientSecret, Number(keys.phonepeClientVersion), env);
|
|
15
15
|
*/
|
|
16
16
|
import { siteSettingsRepository } from "../repositories";
|
|
17
17
|
import { normalizeError } from "../errors/normalize";
|
|
18
18
|
const EMPTY_KEYS = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
phonepeClientId: "",
|
|
20
|
+
phonepeClientSecret: "",
|
|
21
|
+
phonepeClientVersion: "",
|
|
22
|
+
phonepeEnvironment: "",
|
|
23
|
+
phonepeWebhookUsername: "",
|
|
24
|
+
phonepeWebhookPassword: "",
|
|
22
25
|
resendApiKey: "",
|
|
23
26
|
whatsappApiKey: "",
|
|
24
27
|
whatsappPhoneNumberId: "",
|
|
@@ -46,9 +49,12 @@ export async function resolveKeys() {
|
|
|
46
49
|
void normalizeError(_err); // Firestore unavailable — fall through to env-based defaults for backward compatibility
|
|
47
50
|
}
|
|
48
51
|
const value = {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
phonepeClientId: db.phonepeClientId || process.env.PHONEPE_CLIENT_ID || "",
|
|
53
|
+
phonepeClientSecret: db.phonepeClientSecret || process.env.PHONEPE_CLIENT_SECRET || "",
|
|
54
|
+
phonepeClientVersion: db.phonepeClientVersion || process.env.PHONEPE_CLIENT_VERSION || "1",
|
|
55
|
+
phonepeEnvironment: db.phonepeEnvironment || process.env.PHONEPE_ENVIRONMENT || "sandbox",
|
|
56
|
+
phonepeWebhookUsername: db.phonepeWebhookUsername || process.env.PHONEPE_WEBHOOK_USERNAME || "",
|
|
57
|
+
phonepeWebhookPassword: db.phonepeWebhookPassword || process.env.PHONEPE_WEBHOOK_PASSWORD || "",
|
|
52
58
|
resendApiKey: db.resendApiKey || process.env.RESEND_API_KEY || "",
|
|
53
59
|
whatsappApiKey: db.whatsappApiKey || process.env.WHATSAPP_API_KEY || "",
|
|
54
60
|
whatsappPhoneNumberId: db.whatsappPhoneNumberId || process.env.WHATSAPP_PHONE_NUMBER_ID || "",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rupee/paise conversion helpers — gateway-agnostic.
|
|
3
|
+
*
|
|
4
|
+
* Every online payment gateway this project has integrated (Razorpay,
|
|
5
|
+
* PhonePe) bills in paise (India's smallest currency unit), so these live
|
|
6
|
+
* outside any specific provider directory.
|
|
7
|
+
*/
|
|
8
|
+
/** Convert rupees (float) → paise (integer) for a gateway's amount field. */
|
|
9
|
+
export declare function rupeesToPaise(rupees: number): number;
|
|
10
|
+
/** Convert paise (integer) → rupees (float). */
|
|
11
|
+
export declare function paiseToRupees(paise: number): number;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rupee/paise conversion helpers — gateway-agnostic.
|
|
3
|
+
*
|
|
4
|
+
* Every online payment gateway this project has integrated (Razorpay,
|
|
5
|
+
* PhonePe) bills in paise (India's smallest currency unit), so these live
|
|
6
|
+
* outside any specific provider directory.
|
|
7
|
+
*/
|
|
8
|
+
/** Convert rupees (float) → paise (integer) for a gateway's amount field. */
|
|
9
|
+
export function rupeesToPaise(rupees) {
|
|
10
|
+
return Math.round(rupees * 100);
|
|
11
|
+
}
|
|
12
|
+
/** Convert paise (integer) → rupees (float). */
|
|
13
|
+
export function paiseToRupees(paise) {
|
|
14
|
+
return paise / 100;
|
|
15
|
+
}
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { AuthorizationError } from "./authorization-error";
|
|
|
9
9
|
export { NotFoundError } from "./not-found-error";
|
|
10
10
|
export { ConflictError } from "./conflict-error";
|
|
11
11
|
export { DatabaseError } from "./database-error";
|
|
12
|
-
export {
|
|
12
|
+
export { PaymentProviderUnreachableError } from "./payment-provider-unreachable";
|
|
13
13
|
export { handleApiError, logError, isAppError } from "./error-handler";
|
|
14
14
|
export { mapToHttpError, HTTP_ERROR_CODES, type MappedError, type HttpErrorCode, } from "./error-mapping";
|
|
15
15
|
export { ERROR_DISPLAY_MAP, getErrorDisplay, toUserMessage, GENERIC_USER_MESSAGE, type ErrorDisplayEntry, } from "./error-display-map";
|
package/dist/errors/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export { AuthorizationError } from "./authorization-error";
|
|
|
12
12
|
export { NotFoundError } from "./not-found-error";
|
|
13
13
|
export { ConflictError } from "./conflict-error";
|
|
14
14
|
export { DatabaseError } from "./database-error";
|
|
15
|
-
export {
|
|
15
|
+
export { PaymentProviderUnreachableError } from "./payment-provider-unreachable";
|
|
16
16
|
// error-handler uses `next/server` — only import in server/API-route contexts
|
|
17
17
|
export { handleApiError, logError, isAppError } from "./error-handler";
|
|
18
18
|
// Code→HTTP mapper (server) — and the i18n / inline-field map (client-safe)
|
|
@@ -282,6 +282,7 @@ export declare const ERROR_MESSAGES: {
|
|
|
282
282
|
readonly INSUFFICIENT_STOCK: "Insufficient stock for one or more items";
|
|
283
283
|
readonly PAYMENT_FAILED: "Payment processing failed";
|
|
284
284
|
readonly PAYMENT_DECLINED: "Payment was declined.";
|
|
285
|
+
readonly ORDER_PLACEMENT_IN_PROGRESS: "Your payment is still being confirmed — please wait a moment and refresh.";
|
|
285
286
|
readonly PAYMENT_TRACKING_INIT_FAILED: "Failed to initialise payment tracking. Please check your order status.";
|
|
286
287
|
readonly PAYMENT_TRACKING_CONNECTION_LOST: "Payment tracking connection lost. Please check your order status.";
|
|
287
288
|
readonly PAYMENT_TRACKING_TIMED_OUT: "Payment confirmation timed out. Please check your order status.";
|
package/dist/errors/messages.js
CHANGED
|
@@ -306,6 +306,7 @@ export const ERROR_MESSAGES = {
|
|
|
306
306
|
INSUFFICIENT_STOCK: "Insufficient stock for one or more items",
|
|
307
307
|
PAYMENT_FAILED: "Payment processing failed",
|
|
308
308
|
PAYMENT_DECLINED: "Payment was declined.",
|
|
309
|
+
ORDER_PLACEMENT_IN_PROGRESS: "Your payment is still being confirmed — please wait a moment and refresh.",
|
|
309
310
|
PAYMENT_TRACKING_INIT_FAILED: "Failed to initialise payment tracking. Please check your order status.",
|
|
310
311
|
PAYMENT_TRACKING_CONNECTION_LOST: "Payment tracking connection lost. Please check your order status.",
|
|
311
312
|
PAYMENT_TRACKING_TIMED_OUT: "Payment confirmation timed out. Please check your order status.",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppError } from "./base-error";
|
|
2
|
-
export class
|
|
2
|
+
export class PaymentProviderUnreachableError extends AppError {
|
|
3
3
|
constructor(message = "Payment provider unreachable", data) {
|
|
4
4
|
super(503, message, "UPSTREAM_UNAVAILABLE", data);
|
|
5
5
|
}
|
|
@@ -34,13 +34,13 @@ export declare const addressFormSchema: z.ZodEffects<z.ZodObject<{
|
|
|
34
34
|
}, "strip", z.ZodTypeAny, {
|
|
35
35
|
country: string;
|
|
36
36
|
label: string;
|
|
37
|
-
isDefault: boolean;
|
|
38
37
|
fullName: string;
|
|
39
38
|
phone: string;
|
|
40
39
|
addressLine1: string;
|
|
41
40
|
city: string;
|
|
42
41
|
state: string;
|
|
43
42
|
postalCode: string;
|
|
43
|
+
isDefault: boolean;
|
|
44
44
|
addressLine2?: string | undefined;
|
|
45
45
|
landmark?: string | undefined;
|
|
46
46
|
}, {
|
|
@@ -58,13 +58,13 @@ export declare const addressFormSchema: z.ZodEffects<z.ZodObject<{
|
|
|
58
58
|
}>, {
|
|
59
59
|
country: string;
|
|
60
60
|
label: string;
|
|
61
|
-
isDefault: boolean;
|
|
62
61
|
fullName: string;
|
|
63
62
|
phone: string;
|
|
64
63
|
addressLine1: string;
|
|
65
64
|
city: string;
|
|
66
65
|
state: string;
|
|
67
66
|
postalCode: string;
|
|
67
|
+
isDefault: boolean;
|
|
68
68
|
addressLine2?: string | undefined;
|
|
69
69
|
landmark?: string | undefined;
|
|
70
70
|
}, {
|
|
@@ -103,49 +103,49 @@ export declare const addressUpdateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
103
103
|
}, "strip", z.ZodTypeAny, {
|
|
104
104
|
country?: string | undefined;
|
|
105
105
|
label?: string | undefined;
|
|
106
|
-
isDefault?: boolean | undefined;
|
|
107
106
|
fullName?: string | undefined;
|
|
108
107
|
phone?: string | undefined;
|
|
109
108
|
addressLine1?: string | undefined;
|
|
110
109
|
city?: string | undefined;
|
|
111
110
|
state?: string | undefined;
|
|
112
111
|
postalCode?: string | undefined;
|
|
112
|
+
isDefault?: boolean | undefined;
|
|
113
113
|
addressLine2?: string | undefined;
|
|
114
114
|
landmark?: string | undefined;
|
|
115
115
|
}, {
|
|
116
116
|
country?: string | undefined;
|
|
117
117
|
label?: string | undefined;
|
|
118
|
-
isDefault?: boolean | undefined;
|
|
119
118
|
fullName?: string | undefined;
|
|
120
119
|
phone?: string | undefined;
|
|
121
120
|
addressLine1?: string | undefined;
|
|
122
121
|
city?: string | undefined;
|
|
123
122
|
state?: string | undefined;
|
|
124
123
|
postalCode?: string | undefined;
|
|
124
|
+
isDefault?: boolean | undefined;
|
|
125
125
|
addressLine2?: string | undefined;
|
|
126
126
|
landmark?: string | undefined;
|
|
127
127
|
}>, {
|
|
128
128
|
country?: string | undefined;
|
|
129
129
|
label?: string | undefined;
|
|
130
|
-
isDefault?: boolean | undefined;
|
|
131
130
|
fullName?: string | undefined;
|
|
132
131
|
phone?: string | undefined;
|
|
133
132
|
addressLine1?: string | undefined;
|
|
134
133
|
city?: string | undefined;
|
|
135
134
|
state?: string | undefined;
|
|
136
135
|
postalCode?: string | undefined;
|
|
136
|
+
isDefault?: boolean | undefined;
|
|
137
137
|
addressLine2?: string | undefined;
|
|
138
138
|
landmark?: string | undefined;
|
|
139
139
|
}, {
|
|
140
140
|
country?: string | undefined;
|
|
141
141
|
label?: string | undefined;
|
|
142
|
-
isDefault?: boolean | undefined;
|
|
143
142
|
fullName?: string | undefined;
|
|
144
143
|
phone?: string | undefined;
|
|
145
144
|
addressLine1?: string | undefined;
|
|
146
145
|
city?: string | undefined;
|
|
147
146
|
state?: string | undefined;
|
|
148
147
|
postalCode?: string | undefined;
|
|
148
|
+
isDefault?: boolean | undefined;
|
|
149
149
|
addressLine2?: string | undefined;
|
|
150
150
|
landmark?: string | undefined;
|
|
151
151
|
}>;
|
|
@@ -177,7 +177,6 @@ export declare const adminAddressCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
177
177
|
}, "strip", z.ZodTypeAny, {
|
|
178
178
|
country: string;
|
|
179
179
|
label: string;
|
|
180
|
-
isDefault: boolean;
|
|
181
180
|
ownerId: string;
|
|
182
181
|
ownerType: "user" | "store";
|
|
183
182
|
fullName: string;
|
|
@@ -186,6 +185,7 @@ export declare const adminAddressCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
186
185
|
city: string;
|
|
187
186
|
state: string;
|
|
188
187
|
postalCode: string;
|
|
188
|
+
isDefault: boolean;
|
|
189
189
|
addressLine2?: string | undefined;
|
|
190
190
|
landmark?: string | undefined;
|
|
191
191
|
}, {
|
|
@@ -205,7 +205,6 @@ export declare const adminAddressCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
205
205
|
}>, {
|
|
206
206
|
country: string;
|
|
207
207
|
label: string;
|
|
208
|
-
isDefault: boolean;
|
|
209
208
|
ownerId: string;
|
|
210
209
|
ownerType: "user" | "store";
|
|
211
210
|
fullName: string;
|
|
@@ -214,6 +213,7 @@ export declare const adminAddressCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
214
213
|
city: string;
|
|
215
214
|
state: string;
|
|
216
215
|
postalCode: string;
|
|
216
|
+
isDefault: boolean;
|
|
217
217
|
addressLine2?: string | undefined;
|
|
218
218
|
landmark?: string | undefined;
|
|
219
219
|
}, {
|
|
@@ -248,7 +248,6 @@ export declare const adminAddressUpdateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
248
248
|
}, "strip", z.ZodTypeAny, {
|
|
249
249
|
country?: string | undefined;
|
|
250
250
|
label?: string | undefined;
|
|
251
|
-
isDefault?: boolean | undefined;
|
|
252
251
|
ownerId?: string | undefined;
|
|
253
252
|
ownerType?: "user" | "store" | undefined;
|
|
254
253
|
fullName?: string | undefined;
|
|
@@ -257,12 +256,12 @@ export declare const adminAddressUpdateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
257
256
|
city?: string | undefined;
|
|
258
257
|
state?: string | undefined;
|
|
259
258
|
postalCode?: string | undefined;
|
|
259
|
+
isDefault?: boolean | undefined;
|
|
260
260
|
addressLine2?: string | undefined;
|
|
261
261
|
landmark?: string | undefined;
|
|
262
262
|
}, {
|
|
263
263
|
country?: string | undefined;
|
|
264
264
|
label?: string | undefined;
|
|
265
|
-
isDefault?: boolean | undefined;
|
|
266
265
|
ownerId?: string | undefined;
|
|
267
266
|
ownerType?: "user" | "store" | undefined;
|
|
268
267
|
fullName?: string | undefined;
|
|
@@ -271,12 +270,12 @@ export declare const adminAddressUpdateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
271
270
|
city?: string | undefined;
|
|
272
271
|
state?: string | undefined;
|
|
273
272
|
postalCode?: string | undefined;
|
|
273
|
+
isDefault?: boolean | undefined;
|
|
274
274
|
addressLine2?: string | undefined;
|
|
275
275
|
landmark?: string | undefined;
|
|
276
276
|
}>, {
|
|
277
277
|
country?: string | undefined;
|
|
278
278
|
label?: string | undefined;
|
|
279
|
-
isDefault?: boolean | undefined;
|
|
280
279
|
ownerId?: string | undefined;
|
|
281
280
|
ownerType?: "user" | "store" | undefined;
|
|
282
281
|
fullName?: string | undefined;
|
|
@@ -285,12 +284,12 @@ export declare const adminAddressUpdateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
285
284
|
city?: string | undefined;
|
|
286
285
|
state?: string | undefined;
|
|
287
286
|
postalCode?: string | undefined;
|
|
287
|
+
isDefault?: boolean | undefined;
|
|
288
288
|
addressLine2?: string | undefined;
|
|
289
289
|
landmark?: string | undefined;
|
|
290
290
|
}, {
|
|
291
291
|
country?: string | undefined;
|
|
292
292
|
label?: string | undefined;
|
|
293
|
-
isDefault?: boolean | undefined;
|
|
294
293
|
ownerId?: string | undefined;
|
|
295
294
|
ownerType?: "user" | "store" | undefined;
|
|
296
295
|
fullName?: string | undefined;
|
|
@@ -299,6 +298,7 @@ export declare const adminAddressUpdateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
299
298
|
city?: string | undefined;
|
|
300
299
|
state?: string | undefined;
|
|
301
300
|
postalCode?: string | undefined;
|
|
301
|
+
isDefault?: boolean | undefined;
|
|
302
302
|
addressLine2?: string | undefined;
|
|
303
303
|
landmark?: string | undefined;
|
|
304
304
|
}>;
|
|
@@ -337,8 +337,6 @@ export declare const adminAddressPatchSchema: z.ZodEffects<z.ZodObject<{
|
|
|
337
337
|
country?: string | undefined;
|
|
338
338
|
label?: string | undefined;
|
|
339
339
|
action?: "ban" | "approve_unban" | "reject_unban" | undefined;
|
|
340
|
-
isDefault?: boolean | undefined;
|
|
341
|
-
banReason?: string | undefined;
|
|
342
340
|
ownerId?: string | undefined;
|
|
343
341
|
ownerType?: "user" | "store" | undefined;
|
|
344
342
|
fullName?: string | undefined;
|
|
@@ -347,14 +345,14 @@ export declare const adminAddressPatchSchema: z.ZodEffects<z.ZodObject<{
|
|
|
347
345
|
city?: string | undefined;
|
|
348
346
|
state?: string | undefined;
|
|
349
347
|
postalCode?: string | undefined;
|
|
348
|
+
isDefault?: boolean | undefined;
|
|
350
349
|
addressLine2?: string | undefined;
|
|
351
350
|
landmark?: string | undefined;
|
|
351
|
+
banReason?: string | undefined;
|
|
352
352
|
}, {
|
|
353
353
|
country?: string | undefined;
|
|
354
354
|
label?: string | undefined;
|
|
355
355
|
action?: "ban" | "approve_unban" | "reject_unban" | undefined;
|
|
356
|
-
isDefault?: boolean | undefined;
|
|
357
|
-
banReason?: string | undefined;
|
|
358
356
|
ownerId?: string | undefined;
|
|
359
357
|
ownerType?: "user" | "store" | undefined;
|
|
360
358
|
fullName?: string | undefined;
|
|
@@ -363,14 +361,14 @@ export declare const adminAddressPatchSchema: z.ZodEffects<z.ZodObject<{
|
|
|
363
361
|
city?: string | undefined;
|
|
364
362
|
state?: string | undefined;
|
|
365
363
|
postalCode?: string | undefined;
|
|
364
|
+
isDefault?: boolean | undefined;
|
|
366
365
|
addressLine2?: string | undefined;
|
|
367
366
|
landmark?: string | undefined;
|
|
367
|
+
banReason?: string | undefined;
|
|
368
368
|
}>, {
|
|
369
369
|
country?: string | undefined;
|
|
370
370
|
label?: string | undefined;
|
|
371
371
|
action?: "ban" | "approve_unban" | "reject_unban" | undefined;
|
|
372
|
-
isDefault?: boolean | undefined;
|
|
373
|
-
banReason?: string | undefined;
|
|
374
372
|
ownerId?: string | undefined;
|
|
375
373
|
ownerType?: "user" | "store" | undefined;
|
|
376
374
|
fullName?: string | undefined;
|
|
@@ -379,14 +377,14 @@ export declare const adminAddressPatchSchema: z.ZodEffects<z.ZodObject<{
|
|
|
379
377
|
city?: string | undefined;
|
|
380
378
|
state?: string | undefined;
|
|
381
379
|
postalCode?: string | undefined;
|
|
380
|
+
isDefault?: boolean | undefined;
|
|
382
381
|
addressLine2?: string | undefined;
|
|
383
382
|
landmark?: string | undefined;
|
|
383
|
+
banReason?: string | undefined;
|
|
384
384
|
}, {
|
|
385
385
|
country?: string | undefined;
|
|
386
386
|
label?: string | undefined;
|
|
387
387
|
action?: "ban" | "approve_unban" | "reject_unban" | undefined;
|
|
388
|
-
isDefault?: boolean | undefined;
|
|
389
|
-
banReason?: string | undefined;
|
|
390
388
|
ownerId?: string | undefined;
|
|
391
389
|
ownerType?: "user" | "store" | undefined;
|
|
392
390
|
fullName?: string | undefined;
|
|
@@ -395,8 +393,10 @@ export declare const adminAddressPatchSchema: z.ZodEffects<z.ZodObject<{
|
|
|
395
393
|
city?: string | undefined;
|
|
396
394
|
state?: string | undefined;
|
|
397
395
|
postalCode?: string | undefined;
|
|
396
|
+
isDefault?: boolean | undefined;
|
|
398
397
|
addressLine2?: string | undefined;
|
|
399
398
|
landmark?: string | undefined;
|
|
399
|
+
banReason?: string | undefined;
|
|
400
400
|
}>;
|
|
401
401
|
export type AdminAddressPatchValues = z.infer<typeof adminAddressPatchSchema>;
|
|
402
402
|
/**
|
|
@@ -41,7 +41,6 @@ export declare const addressFirestoreSchema: z.ZodObject<{
|
|
|
41
41
|
updatedAt: string | Date | z.objectOutputType<{
|
|
42
42
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
43
43
|
}, z.ZodTypeAny, "passthrough">;
|
|
44
|
-
isDefault: boolean;
|
|
45
44
|
ownerId: string;
|
|
46
45
|
ownerType: "user" | "store";
|
|
47
46
|
fullName: string;
|
|
@@ -50,6 +49,7 @@ export declare const addressFirestoreSchema: z.ZodObject<{
|
|
|
50
49
|
city: string;
|
|
51
50
|
state: string;
|
|
52
51
|
postalCode: string;
|
|
52
|
+
isDefault: boolean;
|
|
53
53
|
addressLine2?: string | undefined;
|
|
54
54
|
landmark?: string | undefined;
|
|
55
55
|
}, {
|
|
@@ -62,7 +62,6 @@ export declare const addressFirestoreSchema: z.ZodObject<{
|
|
|
62
62
|
updatedAt: string | Date | z.objectInputType<{
|
|
63
63
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
64
64
|
}, z.ZodTypeAny, "passthrough">;
|
|
65
|
-
isDefault: boolean;
|
|
66
65
|
ownerId: string;
|
|
67
66
|
ownerType: "user" | "store";
|
|
68
67
|
fullName: string;
|
|
@@ -71,6 +70,7 @@ export declare const addressFirestoreSchema: z.ZodObject<{
|
|
|
71
70
|
city: string;
|
|
72
71
|
state: string;
|
|
73
72
|
postalCode: string;
|
|
73
|
+
isDefault: boolean;
|
|
74
74
|
addressLine2?: string | undefined;
|
|
75
75
|
landmark?: string | undefined;
|
|
76
76
|
}>;
|
|
@@ -210,9 +210,12 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
210
210
|
const [platformShippingPercent, setPlatformShippingPercent] = React.useState(10);
|
|
211
211
|
const [platformShippingFixedMin, setPlatformShippingFixedMin] = React.useState(0);
|
|
212
212
|
// ⑧ Integrations
|
|
213
|
-
const [
|
|
214
|
-
const [
|
|
215
|
-
const [
|
|
213
|
+
const [phonepeClientId, setPhonepeClientId] = React.useState("");
|
|
214
|
+
const [phonepeClientSecret, setPhonepeClientSecret] = React.useState("");
|
|
215
|
+
const [phonepeClientVersion, setPhonepeClientVersion] = React.useState("1");
|
|
216
|
+
const [phonepeEnvironment, setPhonepeEnvironment] = React.useState("sandbox");
|
|
217
|
+
const [phonepeWebhookUsername, setPhonepeWebhookUsername] = React.useState("");
|
|
218
|
+
const [phonepeWebhookPassword, setPhonepeWebhookPassword] = React.useState("");
|
|
216
219
|
const [smtpHost, setSmtpHost] = React.useState("");
|
|
217
220
|
const [smtpPort, setSmtpPort] = React.useState("587");
|
|
218
221
|
const [smtpUser, setSmtpUser] = React.useState("");
|
|
@@ -235,7 +238,7 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
235
238
|
const [defaultCarrier, setDefaultCarrier] = React.useState("custom");
|
|
236
239
|
const [maxDeliveryRadius, setMaxDeliveryRadius] = React.useState(0);
|
|
237
240
|
// ⑨ Payment methods (siteSettings.payment — read by checkout for method eligibility)
|
|
238
|
-
const [
|
|
241
|
+
const [phonepeEnabled, setPhonepeEnabled] = React.useState(false);
|
|
239
242
|
const [upiManualEnabled, setUpiManualEnabled] = React.useState(true);
|
|
240
243
|
const [codEnabled, setCodEnabled] = React.useState(true);
|
|
241
244
|
const [otpCheckoutThreshold, setOtpCheckoutThreshold] = React.useState(5000);
|
|
@@ -417,9 +420,12 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
417
420
|
setGstin(s.gst?.gstin ?? "");
|
|
418
421
|
setGstLegalName(s.gst?.legalName ?? "");
|
|
419
422
|
setGstAddress(s.gst?.address ?? "");
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
+
setPhonepeClientId(s.credentialsMasked?.phonepeClientId ?? "");
|
|
424
|
+
setPhonepeClientSecret(s.credentialsMasked?.phonepeClientSecret ?? "");
|
|
425
|
+
setPhonepeClientVersion(s.credentialsMasked?.phonepeClientVersion ?? "1");
|
|
426
|
+
setPhonepeEnvironment(s.credentialsMasked?.phonepeEnvironment ?? "sandbox");
|
|
427
|
+
setPhonepeWebhookUsername(s.credentialsMasked?.phonepeWebhookUsername ?? "");
|
|
428
|
+
setPhonepeWebhookPassword(s.credentialsMasked?.phonepeWebhookPassword ?? "");
|
|
423
429
|
setGoogleMapsApiKey(s.credentialsMasked?.googleMapsApiKey ?? "");
|
|
424
430
|
setGooglePlaceId(s.credentialsMasked?.googlePlaceId ?? "");
|
|
425
431
|
setSmtpHost(s.emailSettings?.host ?? "");
|
|
@@ -439,7 +445,7 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
439
445
|
setFreeShippingThreshold(s.shipping?.freeShippingThreshold ?? 999);
|
|
440
446
|
setDefaultCarrier(s.shipping?.defaultCarrier ?? "custom");
|
|
441
447
|
setMaxDeliveryRadius(s.shipping?.maxDeliveryRadius ?? 0);
|
|
442
|
-
|
|
448
|
+
setPhonepeEnabled(s.payment?.phonepeEnabled ?? false);
|
|
443
449
|
setUpiManualEnabled(s.payment?.upiManualEnabled ?? true);
|
|
444
450
|
setCodEnabled(s.payment?.codEnabled ?? true);
|
|
445
451
|
setOtpCheckoutThreshold(s.payment?.otpCheckoutThreshold ?? 5000);
|
|
@@ -508,9 +514,12 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
508
514
|
setMsgCeilingEmail(s.messaging?.dailyCeiling?.email ?? 80);
|
|
509
515
|
setMsgCeilingWhatsapp(s.messaging?.dailyCeiling?.whatsapp ?? 200);
|
|
510
516
|
originalMaskedRef.current = {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
517
|
+
phonepeClientId: s.credentialsMasked?.phonepeClientId ?? "",
|
|
518
|
+
phonepeClientSecret: s.credentialsMasked?.phonepeClientSecret ?? "",
|
|
519
|
+
phonepeClientVersion: s.credentialsMasked?.phonepeClientVersion ?? "",
|
|
520
|
+
phonepeEnvironment: s.credentialsMasked?.phonepeEnvironment ?? "",
|
|
521
|
+
phonepeWebhookUsername: s.credentialsMasked?.phonepeWebhookUsername ?? "",
|
|
522
|
+
phonepeWebhookPassword: s.credentialsMasked?.phonepeWebhookPassword ?? "",
|
|
514
523
|
googleMapsApiKey: s.credentialsMasked?.googleMapsApiKey ?? "",
|
|
515
524
|
googlePlaceId: s.credentialsMasked?.googlePlaceId ?? "",
|
|
516
525
|
metaPageAccessToken: s.credentialsMasked?.metaPageAccessToken ?? "",
|
|
@@ -616,9 +625,12 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
616
625
|
// "" field, so an unedited tab never overwrites a real secret with its
|
|
617
626
|
// own masked display string.
|
|
618
627
|
credentials: {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
628
|
+
phonepeClientId: maskedOrReal("phonepeClientId", phonepeClientId),
|
|
629
|
+
phonepeClientSecret: maskedOrReal("phonepeClientSecret", phonepeClientSecret),
|
|
630
|
+
phonepeClientVersion: maskedOrReal("phonepeClientVersion", phonepeClientVersion),
|
|
631
|
+
phonepeEnvironment: maskedOrReal("phonepeEnvironment", phonepeEnvironment),
|
|
632
|
+
phonepeWebhookUsername: maskedOrReal("phonepeWebhookUsername", phonepeWebhookUsername),
|
|
633
|
+
phonepeWebhookPassword: maskedOrReal("phonepeWebhookPassword", phonepeWebhookPassword),
|
|
622
634
|
googleMapsApiKey: maskedOrReal("googleMapsApiKey", googleMapsApiKey),
|
|
623
635
|
googlePlaceId: maskedOrReal("googlePlaceId", googlePlaceId),
|
|
624
636
|
metaPageAccessToken: maskedOrReal("metaPageAccessToken", metaPageAccessToken),
|
|
@@ -665,7 +677,7 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
665
677
|
},
|
|
666
678
|
integrations: { googleAnalyticsId: gaMeasurementId, facebookPixelId: fbPixelId, gtmContainerId },
|
|
667
679
|
shipping: { freeShippingThreshold, defaultCarrier, maxDeliveryRadius },
|
|
668
|
-
payment: {
|
|
680
|
+
payment: { phonepeEnabled, upiManualEnabled, codEnabled, otpCheckoutThreshold },
|
|
669
681
|
auctionConfig: { bidIncrementTiers: bidIncrementTiers, autoExtendWindowMinutes: autoExtendWindow, settlementGracePeriodHours: settlementGrace },
|
|
670
682
|
platformLimits: { maxProductsPerStore, maxCustomFieldsPerProduct: maxCustomFields, maxCustomSectionsPerProduct: maxCustomSections, orderCancellationWindowHours: orderCancelWindow },
|
|
671
683
|
legalPages: { terms: termsHtml, privacy: privacyHtml, refundPolicy: refundHtml, shipping: shippingPolicyHtml, cookies: cookieHtml, ethics: ethicsHtml, codeOfConduct: conductHtml },
|
|
@@ -720,6 +732,10 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
720
732
|
{ label: "Bluedart", value: "bluedart" },
|
|
721
733
|
{ label: "FedEx", value: "fedex" },
|
|
722
734
|
];
|
|
735
|
+
const PHONEPE_ENVIRONMENT_OPTIONS = [
|
|
736
|
+
{ label: "Sandbox (test)", value: "sandbox" },
|
|
737
|
+
{ label: "Production (live)", value: "production" },
|
|
738
|
+
];
|
|
723
739
|
const LISTING_TYPE_KEYS = ["standard", "auction", "pre-order", "prize-draw", "bundle", "classified", "digital-code", "live"];
|
|
724
740
|
const CATEGORY_TYPE_KEYS = ["category", "sublisting", "brand", "bundle"];
|
|
725
741
|
const NOTIF_TYPE_OPTIONS = NOTIFICATION_TYPE_TABS.filter((t) => t.id !== "All").map((t) => ({ value: t.id, label: t.label }));
|
|
@@ -767,7 +783,7 @@ export function AdminSiteSettingsView({ labels = {}, ...rest }) {
|
|
|
767
783
|
{ label: "Top right", value: "top-right" },
|
|
768
784
|
{ label: "Bottom left", value: "bottom-left" },
|
|
769
785
|
{ label: "Bottom right", value: "bottom-right" },
|
|
770
|
-
], value: watermarkPosition, onValueChange: (v) => setWatermarkPosition(v), disabled: watermarkUseCustomOffset }), _jsx(Toggle, { checked: watermarkUseCustomOffset, onChange: setWatermarkUseCustomOffset, label: "Use a custom X/Y offset instead" }), watermarkUseCustomOffset && (_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "X offset (%) \u2014 + right / \u2212 left of center", value: String(watermarkOffsetX), onChange: (e) => setWatermarkOffsetX(Math.max(-45, Math.min(45, parseInt(e.target.value) || 0))), type: "number", min: -45, max: 45 }), _jsx(Input, { label: "Y offset (%) \u2014 + down / \u2212 up from center", value: String(watermarkOffsetY), onChange: (e) => setWatermarkOffsetY(Math.max(-45, Math.min(45, parseInt(e.target.value) || 0))), type: "number", min: -45, max: 45 })] })), _jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Preview (text watermark only)" }), _jsx(Row, { surface: "default", justify: "end", align: "end", className: `relative h-32 ${__O.hidden}`, rounded: "default", children: _jsx(Span, { ref: watermarkPreviewRef, weight: "medium", color: "faint", padding: "1", className: "select-none", children: watermarkText }) })] })] }) }), _jsx(TabsContent, { value: "fees", children: _jsxs(SettingsTabForm, { id: "fees", label: "Fees", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Platform fee \u2014 our cut (%)", helperText: "% charged on order value. Buyer pays this.", value: String(platformFeePercent), onChange: (e) => setPlatformFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "GST on platform fee (%)", helperText: "Applied to our fee only (not full order). Usually 18%.", value: String(gstPercent), onChange: (e) => setGstPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "Razorpay gateway cost (%)", helperText: "Gateway's own fee \u2014 absorbed by platform, not passed through.", value: String(gatewayFeePercent), onChange: (e) => setGatewayFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 10, step: 0.01 }), _jsx(Input, { label: "Minimum transaction fee (\u20B9)", helperText: "Per-transaction floor. Total charge will never be below base + this.", value: String(minimumTransactionFee), onChange: (e) => setMinimumTransactionFee(parseFloat(e.target.value) || 0), type: "number", min: 0, step: 0.01 }), _jsx(Input, { label: "Maximum platform fee (\u20B9)", helperText: "Ceiling on the buyer's platform commission, charged once per checkout on every payment method. GST is calculated on the capped amount.", value: String(platformFeeMax), onChange: (e) => setPlatformFeeMax(parseFloat(e.target.value) || 0), type: "number", min: 0, step: 0.01 }), _jsx(Input, { label: "Seller payout hold (days)", value: String(payoutHoldDays), onChange: (e) => setPayoutHoldDays(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Minimum payout amount (\u20B9)", value: String(minPayoutAmount), onChange: (e) => setMinPayoutAmount(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Auction listing fee (\u20B9)", value: String(auctionListingFee), onChange: (e) => setAuctionListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Pre-order listing fee (\u20B9)", value: String(preOrderListingFee), onChange: (e) => setPreOrderListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Featured slot fee (\u20B9)", value: String(featuredSlotFee), onChange: (e) => setFeaturedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Promoted slot fee (\u20B9)", value: String(promotedSlotFee), onChange: (e) => setPromotedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "COD deposit (%)", helperText: "% of order collected upfront on COD orders; remainder paid on delivery.", value: String(codDepositPercent), onChange: (e) => setCodDepositPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 })] }), _jsx(Toggle, { checked: whatsappNotifyFeeEnabled, onChange: setWhatsappNotifyFeeEnabled, label: "Offer the WhatsApp order-updates addon at checkout" }), _jsx(Grid, { cols: 2, gap: "md", children: _jsx(Input, { label: "WhatsApp addon fee (\u20B9)", helperText: "Flat fee charged to the buyer when they opt in. Requires WhatsApp credentials + at least one approved template \u2014 see the WhatsApp tab.", value: String(whatsappNotifyFee), onChange: (e) => setWhatsappNotifyFee(parseFloat(e.target.value) || 0), type: "number", min: 0, disabled: !whatsappNotifyFeeEnabled }) }), _jsx(Toggle, { checked: giftWrapFeeEnabled, onChange: setGiftWrapFeeEnabled, label: "Offer the gift-wrap addon at checkout" }), _jsx(Grid, { cols: 2, gap: "md", children: _jsx(Input, { label: "Gift wrap fee (\u20B9)", helperText: "Flat fee charged to the buyer when they opt in.", value: String(giftWrapFee), onChange: (e) => setGiftWrapFee(parseFloat(e.target.value) || 0), type: "number", min: 0, disabled: !giftWrapFeeEnabled }) }), _jsx(Toggle, { checked: shipmentProtectionFeeEnabled, onChange: setShipmentProtectionFeeEnabled, label: "Offer the shipment-protection addon at checkout" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Shipment protection (%)", helperText: "% of order subtotal, charged when the buyer opts in.", value: String(shipmentProtectionFeePercent), onChange: (e) => setShipmentProtectionFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1, disabled: !shipmentProtectionFeeEnabled }), _jsx(Input, { label: "Shipment protection minimum (\u20B9)", helperText: "Floor for the shipment-protection fee.", value: String(shipmentProtectionFeeMin), onChange: (e) => setShipmentProtectionFeeMin(parseFloat(e.target.value) || 0), type: "number", min: 0, disabled: !shipmentProtectionFeeEnabled })] })] }) }), _jsx(TabsContent, { value: "procurement", children: _jsxs(SettingsTabForm, { id: "procurement", label: "Procurement", children: [_jsx(Text, { size: "xs", color: "muted", children: "Used to compute each procurement shipment's labor cost (hours spent \u00D7 hourly rate) and its estimated processing time (hours spent \u00F7 max hours/day)." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Hourly rate (\u20B9)", helperText: "Your effective hourly wage for sorting/categorizing/listing a shipment.", value: String(laborHourlyRate), onChange: (e) => setLaborHourlyRate(Math.round((parseFloat(e.target.value) || 0) * 100) / 100), type: "number", min: 0 }), _jsx(Input, { label: "Max hours per day", helperText: "Used only to project how many days a shipment's tracked hours will take.", value: String(laborMaxHoursPerDay), onChange: (e) => setLaborMaxHoursPerDay(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 24 })] })] }) }), _jsx(TabsContent, { value: "emi", children: _jsxs(SettingsTabForm, { id: "emi", label: "Emi", children: [_jsx(Text, { size: "xs", color: "muted", children: "A seller must also opt in via their own Payout Settings for EMI to appear at checkout on their items. See the \"How EMI Works\" public page for buyer-facing copy." }), _jsx(Toggle, { checked: emiEnabled, onChange: setEmiEnabled, label: "Enable EMI platform-wide" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Minimum order value (\u20B9)", helperText: "A seller's cart subtotal must exceed this for EMI to appear as an option.", value: String(emiMinOrderValue), onChange: (e) => setEmiMinOrderValue(Math.round((parseFloat(e.target.value) || 0) * 100) / 100), type: "number", min: 0 }), _jsx(Input, { label: "Tenure options (months, comma-separated)", helperText: "e.g. 2,3,4,5,6", value: emiTenureOptionsText, onChange: (e) => setEmiTenureOptionsText(e.target.value) }), _jsx(Input, { label: "Token / down-payment (%)", helperText: "Collected upfront at checkout.", value: String(emiTokenPercent), onChange: (e) => setEmiTokenPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100 }), _jsx(Input, { label: "Billing day (1\u201310)", helperText: "Day of month each installment is due.", value: String(emiBillingDay), onChange: (e) => setEmiBillingDay(parseFloat(e.target.value) || 1), type: "number", min: 1, max: 10 }), _jsx(Input, { label: "Surcharge (% of principal per month)", helperText: "The 'excess EMI fee' the buyer pays for spreading payment.", value: String(emiSurchargePercentPerMonth), onChange: (e) => setEmiSurchargePercentPerMonth(parseFloat(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Seller's share of surcharge (%)", helperText: "The rest of the surcharge goes to the platform.", value: String(emiSurchargeSellerSharePercent), onChange: (e) => setEmiSurchargeSellerSharePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100 })] })] }) }), _jsx(TabsContent, { value: "gst", children: _jsxs(SettingsTabForm, { id: "gst", label: "Gst", children: [_jsx(Text, { size: "xs", color: "muted", children: "Required before enabling GST-inclusive checkout (P-8). Also set a GST rate + HSN code on each taxable product for the tax breakdown to appear." }), _jsx(Toggle, { checked: gstEnabled, onChange: setGstEnabled, label: "Enable GST on checkout" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "GSTIN", helperText: "15-character GST Identification Number.", value: gstin, onChange: (e) => setGstin(e.target.value), placeholder: "29AAAAA0000A1Z5", maxLength: 15 }), _jsx(Input, { label: "Legal name", helperText: "Registered business name for invoices.", value: gstLegalName, onChange: (e) => setGstLegalName(e.target.value), placeholder: "LetItRip Collectibles Pvt Ltd" })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Registered address" }), _jsx(Textarea, { value: gstAddress, onChange: (e) => setGstAddress(e.target.value), placeholder: "Registered business address for GST invoices\u2026", rows: 3 })] })] }) }), _jsx(TabsContent, { value: "listings", children: _jsxs(SettingsTabForm, { id: "listings", label: "Listings", children: [_jsx(Text, { size: "xs", color: "muted", children: "Which listing and category types the marketplace offers. A disabled type is hidden from every browse surface and rejected on create and add-to-cart \u2014 existing data is untouched, it just becomes unreachable until re-enabled." }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Listing types" }), _jsx(Text, { size: "xs", color: "muted", children: "Disabled types are hidden from listings and reject create/add-to-cart." }), _jsx(Grid, { cols: 2, gap: "sm", children: LISTING_TYPE_KEYS.map((key) => (_jsx(Toggle, { label: key, checked: listingTypeFlags[key] ?? true, onChange: (v) => setListingTypeFlags((prev) => ({ ...prev, [key]: v })) }, key))) })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Category types" }), _jsx(Grid, { cols: 2, gap: "sm", children: CATEGORY_TYPE_KEYS.map((key) => (_jsx(Toggle, { label: key, checked: categoryTypeFlags[key] ?? true, onChange: (v) => setCategoryTypeFlags((prev) => ({ ...prev, [key]: v })) }, key))) })] })] }) }), _jsx(TabsContent, { value: "integrations", children: _jsxs(SettingsTabForm, { id: "integrations", label: "Integrations", children: [_jsx(Text, { size: "xs", color: "muted", children: "Keys are masked in transit and stored encrypted. Click Reveal to view." }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Razorpay" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Razorpay Key ID", value: razorpayKeyId, onChange: setRazorpayKeyId, placeholder: "rzp_live_\u2026" }), _jsx(MaskedInput, { label: "Razorpay Key Secret", value: razorpayKeySecret, onChange: setRazorpayKeySecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(MaskedInput, { label: "Razorpay Webhook Secret", value: razorpayWebhookSecret, onChange: setRazorpayWebhookSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "SMTP / Email" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "SMTP host", value: smtpHost, onChange: (e) => setSmtpHost(e.target.value), placeholder: "smtp.sendgrid.net" }), _jsx(Input, { label: "SMTP port", value: smtpPort, onChange: (e) => setSmtpPort(e.target.value), type: "number", placeholder: "587" }), _jsx(Input, { label: "SMTP user", value: smtpUser, onChange: (e) => setSmtpUser(e.target.value), placeholder: "apikey" })] }), _jsx(Input, { label: "From address", value: smtpFrom, onChange: (e) => setSmtpFrom(e.target.value), placeholder: "noreply@letitrip.in", type: "email" }), _jsx(Text, { size: "xs", color: "muted", children: "Transactional email is delivered through Resend \u2014 set the Resend API key below. These SMTP fields are stored but not currently used for delivery." })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Google Places (store reviews)" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Google Maps API key", value: googleMapsApiKey, onChange: setGoogleMapsApiKey, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(Input, { label: "Default Google Place ID", value: googlePlaceId, onChange: (e) => setGooglePlaceId(e.target.value), placeholder: "ChIJ\u2026" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Analytics & Tracking" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Google Analytics ID", value: gaMeasurementId, onChange: (e) => setGaMeasurementId(e.target.value), placeholder: "G-XXXXXXXXXX" }), _jsx(Input, { label: "Facebook Pixel ID", value: fbPixelId, onChange: (e) => setFbPixelId(e.target.value), placeholder: "XXXXXXXXXXXXXXXX" }), _jsx(Input, { label: "GTM Container ID", value: gtmContainerId, onChange: (e) => setGtmContainerId(e.target.value), placeholder: "GTM-XXXXXXX" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Meta (Instagram & Facebook Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Used by the Social Feed section to fetch Instagram and Facebook posts via Meta Graph API v19." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Page Access Token", value: metaPageAccessToken, onChange: setMetaPageAccessToken, placeholder: "EAAxxxxxxx\u2026" }), _jsx(Input, { label: "Page ID (or handle)", value: metaPageId, onChange: (e) => setMetaPageId(e.target.value), placeholder: "letitrip" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "TikTok for Developers (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials + long-lived access token from TikTok for Developers. Used to list your account's public videos." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client Key", value: tiktokClientKey, onChange: setTiktokClientKey, placeholder: "aw\u2026" }), _jsx(MaskedInput, { label: "Client Secret", value: tiktokClientSecret, onChange: setTiktokClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(MaskedInput, { label: "Access Token (long-lived)", value: tiktokAccessToken, onChange: setTiktokAccessToken, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "DeviantArt OAuth2 (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials for DeviantArt gallery fetching (client-credentials OAuth2 flow \u2014 no user login required)." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client ID", value: deviantartClientId, onChange: setDeviantartClientId, placeholder: "1234" }), _jsx(MaskedInput, { label: "Client Secret", value: deviantartClientSecret, onChange: setDeviantartClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] })] }) }), _jsx(TabsContent, { value: "shipping", children: _jsxs(SettingsTabForm, { id: "shipping", label: "Shipping", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Payment methods" }), _jsx(Div, { id: "setting-razorpay-enabled", children: _jsx(Toggle, { label: "Razorpay (online card/UPI) enabled \u2014 disabled by default, manual payment is the default", checked: razorpayEnabled, onChange: setRazorpayEnabled }) }), _jsx(Div, { id: "setting-manual-payment-enabled", children: _jsx(Toggle, { label: "Manual UPI/bank transfer enabled", checked: upiManualEnabled, onChange: setUpiManualEnabled }) }), _jsx(Div, { id: "setting-cod-enabled", children: _jsx(Toggle, { label: "Cash on delivery (COD) enabled", checked: codEnabled, onChange: setCodEnabled }) }), _jsx(Input, { label: "Free shipping threshold (\u20B9)", value: String(freeShippingThreshold), onChange: (e) => setFreeShippingThreshold(parseInt(e.target.value) || 0), type: "number", min: 0, helperText: "Orders above this amount get free shipping." }), _jsx(Select, { label: "Default carrier", options: CARRIER_OPTIONS, value: defaultCarrier, onValueChange: setDefaultCarrier }), _jsx(Input, { label: "Max delivery radius (km, 0 = no limit)", value: String(maxDeliveryRadius), onChange: (e) => setMaxDeliveryRadius(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "High-value checkout OTP threshold (\u20B9)", helperText: "Carts at or above this subtotal require an extra OTP verification step before payment (0 = disabled).", value: String(otpCheckoutThreshold), onChange: (e) => setOtpCheckoutThreshold(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Text, { size: "sm", weight: "medium", color: "muted", className: "pt-[var(--appkit-space-2)]", children: "Seller shipping charge defaults" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Seller shipping fixed (\u20B9)", helperText: "Flat shipping charge collected on the seller's behalf.", value: String(sellerShippingFixed), onChange: (e) => setSellerShippingFixed(parseFloat(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Platform shipping (%)", helperText: "Platform's own shipping markup, as a % of order value.", value: String(platformShippingPercent), onChange: (e) => setPlatformShippingPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "Platform shipping minimum (\u20B9)", helperText: "Floor for the platform shipping markup.", value: String(platformShippingFixedMin), onChange: (e) => setPlatformShippingFixedMin(parseFloat(e.target.value) || 0), type: "number", min: 0 })] })] }) }), _jsx(TabsContent, { value: "auction", children: _jsxs(SettingsTabForm, { id: "auction", label: "Auction", children: [_jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "xs", weight: "medium", color: "muted", children: "Bid increment tiers" }), _jsx(Text, { size: "xs", color: "muted", children: "The minimum jump a new bid must clear, based on the current bid amount. A seller's per-listing override can require more than the matching tier, but can never undercut it." }), bidIncrementTiers.map((tier, i) => {
|
|
786
|
+
], value: watermarkPosition, onValueChange: (v) => setWatermarkPosition(v), disabled: watermarkUseCustomOffset }), _jsx(Toggle, { checked: watermarkUseCustomOffset, onChange: setWatermarkUseCustomOffset, label: "Use a custom X/Y offset instead" }), watermarkUseCustomOffset && (_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "X offset (%) \u2014 + right / \u2212 left of center", value: String(watermarkOffsetX), onChange: (e) => setWatermarkOffsetX(Math.max(-45, Math.min(45, parseInt(e.target.value) || 0))), type: "number", min: -45, max: 45 }), _jsx(Input, { label: "Y offset (%) \u2014 + down / \u2212 up from center", value: String(watermarkOffsetY), onChange: (e) => setWatermarkOffsetY(Math.max(-45, Math.min(45, parseInt(e.target.value) || 0))), type: "number", min: -45, max: 45 })] })), _jsxs(Stack, { gap: "xs", surface: "muted", rounded: "lg", border: "default", padding: "md", children: [_jsx(Text, { size: "xs", color: "muted", children: "Preview (text watermark only)" }), _jsx(Row, { surface: "default", justify: "end", align: "end", className: `relative h-32 ${__O.hidden}`, rounded: "default", children: _jsx(Span, { ref: watermarkPreviewRef, weight: "medium", color: "faint", padding: "1", className: "select-none", children: watermarkText }) })] })] }) }), _jsx(TabsContent, { value: "fees", children: _jsxs(SettingsTabForm, { id: "fees", label: "Fees", children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Platform fee \u2014 our cut (%)", helperText: "% charged on order value. Buyer pays this.", value: String(platformFeePercent), onChange: (e) => setPlatformFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "GST on platform fee (%)", helperText: "Applied to our fee only (not full order). Usually 18%.", value: String(gstPercent), onChange: (e) => setGstPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "PhonePe gateway cost (%)", helperText: "Gateway's own fee \u2014 absorbed by platform, not passed through.", value: String(gatewayFeePercent), onChange: (e) => setGatewayFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 10, step: 0.01 }), _jsx(Input, { label: "Minimum transaction fee (\u20B9)", helperText: "Per-transaction floor. Total charge will never be below base + this.", value: String(minimumTransactionFee), onChange: (e) => setMinimumTransactionFee(parseFloat(e.target.value) || 0), type: "number", min: 0, step: 0.01 }), _jsx(Input, { label: "Maximum platform fee (\u20B9)", helperText: "Ceiling on the buyer's platform commission, charged once per checkout on every payment method. GST is calculated on the capped amount.", value: String(platformFeeMax), onChange: (e) => setPlatformFeeMax(parseFloat(e.target.value) || 0), type: "number", min: 0, step: 0.01 }), _jsx(Input, { label: "Seller payout hold (days)", value: String(payoutHoldDays), onChange: (e) => setPayoutHoldDays(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Minimum payout amount (\u20B9)", value: String(minPayoutAmount), onChange: (e) => setMinPayoutAmount(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Auction listing fee (\u20B9)", value: String(auctionListingFee), onChange: (e) => setAuctionListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Pre-order listing fee (\u20B9)", value: String(preOrderListingFee), onChange: (e) => setPreOrderListingFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Featured slot fee (\u20B9)", value: String(featuredSlotFee), onChange: (e) => setFeaturedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Promoted slot fee (\u20B9)", value: String(promotedSlotFee), onChange: (e) => setPromotedSlotFee(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "COD deposit (%)", helperText: "% of order collected upfront on COD orders; remainder paid on delivery.", value: String(codDepositPercent), onChange: (e) => setCodDepositPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 })] }), _jsx(Toggle, { checked: whatsappNotifyFeeEnabled, onChange: setWhatsappNotifyFeeEnabled, label: "Offer the WhatsApp order-updates addon at checkout" }), _jsx(Grid, { cols: 2, gap: "md", children: _jsx(Input, { label: "WhatsApp addon fee (\u20B9)", helperText: "Flat fee charged to the buyer when they opt in. Requires WhatsApp credentials + at least one approved template \u2014 see the WhatsApp tab.", value: String(whatsappNotifyFee), onChange: (e) => setWhatsappNotifyFee(parseFloat(e.target.value) || 0), type: "number", min: 0, disabled: !whatsappNotifyFeeEnabled }) }), _jsx(Toggle, { checked: giftWrapFeeEnabled, onChange: setGiftWrapFeeEnabled, label: "Offer the gift-wrap addon at checkout" }), _jsx(Grid, { cols: 2, gap: "md", children: _jsx(Input, { label: "Gift wrap fee (\u20B9)", helperText: "Flat fee charged to the buyer when they opt in.", value: String(giftWrapFee), onChange: (e) => setGiftWrapFee(parseFloat(e.target.value) || 0), type: "number", min: 0, disabled: !giftWrapFeeEnabled }) }), _jsx(Toggle, { checked: shipmentProtectionFeeEnabled, onChange: setShipmentProtectionFeeEnabled, label: "Offer the shipment-protection addon at checkout" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Shipment protection (%)", helperText: "% of order subtotal, charged when the buyer opts in.", value: String(shipmentProtectionFeePercent), onChange: (e) => setShipmentProtectionFeePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1, disabled: !shipmentProtectionFeeEnabled }), _jsx(Input, { label: "Shipment protection minimum (\u20B9)", helperText: "Floor for the shipment-protection fee.", value: String(shipmentProtectionFeeMin), onChange: (e) => setShipmentProtectionFeeMin(parseFloat(e.target.value) || 0), type: "number", min: 0, disabled: !shipmentProtectionFeeEnabled })] })] }) }), _jsx(TabsContent, { value: "procurement", children: _jsxs(SettingsTabForm, { id: "procurement", label: "Procurement", children: [_jsx(Text, { size: "xs", color: "muted", children: "Used to compute each procurement shipment's labor cost (hours spent \u00D7 hourly rate) and its estimated processing time (hours spent \u00F7 max hours/day)." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Hourly rate (\u20B9)", helperText: "Your effective hourly wage for sorting/categorizing/listing a shipment.", value: String(laborHourlyRate), onChange: (e) => setLaborHourlyRate(Math.round((parseFloat(e.target.value) || 0) * 100) / 100), type: "number", min: 0 }), _jsx(Input, { label: "Max hours per day", helperText: "Used only to project how many days a shipment's tracked hours will take.", value: String(laborMaxHoursPerDay), onChange: (e) => setLaborMaxHoursPerDay(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 24 })] })] }) }), _jsx(TabsContent, { value: "emi", children: _jsxs(SettingsTabForm, { id: "emi", label: "Emi", children: [_jsx(Text, { size: "xs", color: "muted", children: "A seller must also opt in via their own Payout Settings for EMI to appear at checkout on their items. See the \"How EMI Works\" public page for buyer-facing copy." }), _jsx(Toggle, { checked: emiEnabled, onChange: setEmiEnabled, label: "Enable EMI platform-wide" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Minimum order value (\u20B9)", helperText: "A seller's cart subtotal must exceed this for EMI to appear as an option.", value: String(emiMinOrderValue), onChange: (e) => setEmiMinOrderValue(Math.round((parseFloat(e.target.value) || 0) * 100) / 100), type: "number", min: 0 }), _jsx(Input, { label: "Tenure options (months, comma-separated)", helperText: "e.g. 2,3,4,5,6", value: emiTenureOptionsText, onChange: (e) => setEmiTenureOptionsText(e.target.value) }), _jsx(Input, { label: "Token / down-payment (%)", helperText: "Collected upfront at checkout.", value: String(emiTokenPercent), onChange: (e) => setEmiTokenPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100 }), _jsx(Input, { label: "Billing day (1\u201310)", helperText: "Day of month each installment is due.", value: String(emiBillingDay), onChange: (e) => setEmiBillingDay(parseFloat(e.target.value) || 1), type: "number", min: 1, max: 10 }), _jsx(Input, { label: "Surcharge (% of principal per month)", helperText: "The 'excess EMI fee' the buyer pays for spreading payment.", value: String(emiSurchargePercentPerMonth), onChange: (e) => setEmiSurchargePercentPerMonth(parseFloat(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Seller's share of surcharge (%)", helperText: "The rest of the surcharge goes to the platform.", value: String(emiSurchargeSellerSharePercent), onChange: (e) => setEmiSurchargeSellerSharePercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100 })] })] }) }), _jsx(TabsContent, { value: "gst", children: _jsxs(SettingsTabForm, { id: "gst", label: "Gst", children: [_jsx(Text, { size: "xs", color: "muted", children: "Required before enabling GST-inclusive checkout (P-8). Also set a GST rate + HSN code on each taxable product for the tax breakdown to appear." }), _jsx(Toggle, { checked: gstEnabled, onChange: setGstEnabled, label: "Enable GST on checkout" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "GSTIN", helperText: "15-character GST Identification Number.", value: gstin, onChange: (e) => setGstin(e.target.value), placeholder: "29AAAAA0000A1Z5", maxLength: 15 }), _jsx(Input, { label: "Legal name", helperText: "Registered business name for invoices.", value: gstLegalName, onChange: (e) => setGstLegalName(e.target.value), placeholder: "LetItRip Collectibles Pvt Ltd" })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Registered address" }), _jsx(Textarea, { value: gstAddress, onChange: (e) => setGstAddress(e.target.value), placeholder: "Registered business address for GST invoices\u2026", rows: 3 })] })] }) }), _jsx(TabsContent, { value: "listings", children: _jsxs(SettingsTabForm, { id: "listings", label: "Listings", children: [_jsx(Text, { size: "xs", color: "muted", children: "Which listing and category types the marketplace offers. A disabled type is hidden from every browse surface and rejected on create and add-to-cart \u2014 existing data is untouched, it just becomes unreachable until re-enabled." }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Listing types" }), _jsx(Text, { size: "xs", color: "muted", children: "Disabled types are hidden from listings and reject create/add-to-cart." }), _jsx(Grid, { cols: 2, gap: "sm", children: LISTING_TYPE_KEYS.map((key) => (_jsx(Toggle, { label: key, checked: listingTypeFlags[key] ?? true, onChange: (v) => setListingTypeFlags((prev) => ({ ...prev, [key]: v })) }, key))) })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Category types" }), _jsx(Grid, { cols: 2, gap: "sm", children: CATEGORY_TYPE_KEYS.map((key) => (_jsx(Toggle, { label: key, checked: categoryTypeFlags[key] ?? true, onChange: (v) => setCategoryTypeFlags((prev) => ({ ...prev, [key]: v })) }, key))) })] })] }) }), _jsx(TabsContent, { value: "integrations", children: _jsxs(SettingsTabForm, { id: "integrations", label: "Integrations", children: [_jsx(Text, { size: "xs", color: "muted", children: "Keys are masked in transit and stored encrypted. Click Reveal to view." }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "PhonePe" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "PhonePe Client ID", value: phonepeClientId, onChange: setPhonepeClientId, placeholder: "MERCHANTID_\u2026" }), _jsx(MaskedInput, { label: "PhonePe Client Secret", value: phonepeClientSecret, onChange: setPhonepeClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(Input, { label: "PhonePe Client Version", value: phonepeClientVersion, onChange: (e) => setPhonepeClientVersion(e.target.value), placeholder: "1" }), _jsx(Select, { label: "PhonePe Environment", options: PHONEPE_ENVIRONMENT_OPTIONS, value: phonepeEnvironment, onValueChange: setPhonepeEnvironment }), _jsx(MaskedInput, { label: "PhonePe Webhook Username", value: phonepeWebhookUsername, onChange: setPhonepeWebhookUsername, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(MaskedInput, { label: "PhonePe Webhook Password", value: phonepeWebhookPassword, onChange: setPhonepeWebhookPassword, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "SMTP / Email" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "SMTP host", value: smtpHost, onChange: (e) => setSmtpHost(e.target.value), placeholder: "smtp.sendgrid.net" }), _jsx(Input, { label: "SMTP port", value: smtpPort, onChange: (e) => setSmtpPort(e.target.value), type: "number", placeholder: "587" }), _jsx(Input, { label: "SMTP user", value: smtpUser, onChange: (e) => setSmtpUser(e.target.value), placeholder: "apikey" })] }), _jsx(Input, { label: "From address", value: smtpFrom, onChange: (e) => setSmtpFrom(e.target.value), placeholder: "noreply@letitrip.in", type: "email" }), _jsx(Text, { size: "xs", color: "muted", children: "Transactional email is delivered through Resend \u2014 set the Resend API key below. These SMTP fields are stored but not currently used for delivery." })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Google Places (store reviews)" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Google Maps API key", value: googleMapsApiKey, onChange: setGoogleMapsApiKey, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(Input, { label: "Default Google Place ID", value: googlePlaceId, onChange: (e) => setGooglePlaceId(e.target.value), placeholder: "ChIJ\u2026" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Analytics & Tracking" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Google Analytics ID", value: gaMeasurementId, onChange: (e) => setGaMeasurementId(e.target.value), placeholder: "G-XXXXXXXXXX" }), _jsx(Input, { label: "Facebook Pixel ID", value: fbPixelId, onChange: (e) => setFbPixelId(e.target.value), placeholder: "XXXXXXXXXXXXXXXX" }), _jsx(Input, { label: "GTM Container ID", value: gtmContainerId, onChange: (e) => setGtmContainerId(e.target.value), placeholder: "GTM-XXXXXXX" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Meta (Instagram & Facebook Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Used by the Social Feed section to fetch Instagram and Facebook posts via Meta Graph API v19." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Page Access Token", value: metaPageAccessToken, onChange: setMetaPageAccessToken, placeholder: "EAAxxxxxxx\u2026" }), _jsx(Input, { label: "Page ID (or handle)", value: metaPageId, onChange: (e) => setMetaPageId(e.target.value), placeholder: "letitrip" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "TikTok for Developers (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials + long-lived access token from TikTok for Developers. Used to list your account's public videos." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client Key", value: tiktokClientKey, onChange: setTiktokClientKey, placeholder: "aw\u2026" }), _jsx(MaskedInput, { label: "Client Secret", value: tiktokClientSecret, onChange: setTiktokClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }), _jsx(MaskedInput, { label: "Access Token (long-lived)", value: tiktokAccessToken, onChange: setTiktokAccessToken, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] }), _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "DeviantArt OAuth2 (Social Feed)" }), _jsx(Text, { size: "xs", color: "muted", children: "Client credentials for DeviantArt gallery fetching (client-credentials OAuth2 flow \u2014 no user login required)." }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(MaskedInput, { label: "Client ID", value: deviantartClientId, onChange: setDeviantartClientId, placeholder: "1234" }), _jsx(MaskedInput, { label: "Client Secret", value: deviantartClientSecret, onChange: setDeviantartClientSecret, placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })] })] })] }) }), _jsx(TabsContent, { value: "shipping", children: _jsxs(SettingsTabForm, { id: "shipping", label: "Shipping", children: [_jsx(Text, { size: "sm", weight: "medium", color: "muted", children: "Payment methods" }), _jsx(Div, { id: "setting-phonepe-enabled", children: _jsx(Toggle, { label: "PhonePe (online card/UPI) enabled \u2014 disabled by default, manual payment is the default", checked: phonepeEnabled, onChange: setPhonepeEnabled }) }), _jsx(Div, { id: "setting-manual-payment-enabled", children: _jsx(Toggle, { label: "Manual UPI/bank transfer enabled", checked: upiManualEnabled, onChange: setUpiManualEnabled }) }), _jsx(Div, { id: "setting-cod-enabled", children: _jsx(Toggle, { label: "Cash on delivery (COD) enabled", checked: codEnabled, onChange: setCodEnabled }) }), _jsx(Input, { label: "Free shipping threshold (\u20B9)", value: String(freeShippingThreshold), onChange: (e) => setFreeShippingThreshold(parseInt(e.target.value) || 0), type: "number", min: 0, helperText: "Orders above this amount get free shipping." }), _jsx(Select, { label: "Default carrier", options: CARRIER_OPTIONS, value: defaultCarrier, onValueChange: setDefaultCarrier }), _jsx(Input, { label: "Max delivery radius (km, 0 = no limit)", value: String(maxDeliveryRadius), onChange: (e) => setMaxDeliveryRadius(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "High-value checkout OTP threshold (\u20B9)", helperText: "Carts at or above this subtotal require an extra OTP verification step before payment (0 = disabled).", value: String(otpCheckoutThreshold), onChange: (e) => setOtpCheckoutThreshold(parseInt(e.target.value) || 0), type: "number", min: 0 }), _jsx(Text, { size: "sm", weight: "medium", color: "muted", className: "pt-[var(--appkit-space-2)]", children: "Seller shipping charge defaults" }), _jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(Input, { label: "Seller shipping fixed (\u20B9)", helperText: "Flat shipping charge collected on the seller's behalf.", value: String(sellerShippingFixed), onChange: (e) => setSellerShippingFixed(parseFloat(e.target.value) || 0), type: "number", min: 0 }), _jsx(Input, { label: "Platform shipping (%)", helperText: "Platform's own shipping markup, as a % of order value.", value: String(platformShippingPercent), onChange: (e) => setPlatformShippingPercent(parseFloat(e.target.value) || 0), type: "number", min: 0, max: 100, step: 0.1 }), _jsx(Input, { label: "Platform shipping minimum (\u20B9)", helperText: "Floor for the platform shipping markup.", value: String(platformShippingFixedMin), onChange: (e) => setPlatformShippingFixedMin(parseFloat(e.target.value) || 0), type: "number", min: 0 })] })] }) }), _jsx(TabsContent, { value: "auction", children: _jsxs(SettingsTabForm, { id: "auction", label: "Auction", children: [_jsxs(Stack, { gap: "sm", rounded: "lg", border: "default", padding: "sm", children: [_jsx(Text, { size: "xs", weight: "medium", color: "muted", children: "Bid increment tiers" }), _jsx(Text, { size: "xs", color: "muted", children: "The minimum jump a new bid must clear, based on the current bid amount. A seller's per-listing override can require more than the matching tier, but can never undercut it." }), bidIncrementTiers.map((tier, i) => {
|
|
771
787
|
const isLast = i === bidIncrementTiers.length - 1;
|
|
772
788
|
return (_jsxs(Grid, { align: "end", gap: "xs", className: "grid-cols-12", children: [_jsx(Div, { className: "col-span-5", children: isLast ? (_jsxs(_Fragment, { children: [_jsx(Text, { size: "xs", weight: "medium", className: "mb-1", children: "Up to (\u20B9)" }), _jsx(Text, { size: "sm", color: "muted", children: "and above" })] })) : (_jsx(Input, { label: "Up to (\u20B9)", type: "number", min: 1, value: String(tier.upTo ?? ""), onChange: (e) => setBidIncrementTiers(bidIncrementTiers.map((t, j) => j === i ? { ...t, upTo: parseInt(e.target.value) || 0 } : t)) })) }), _jsx(Div, { className: "col-span-5", children: _jsx(Input, { label: "Increment (\u20B9)", type: "number", min: 1, value: String(tier.increment), onChange: (e) => setBidIncrementTiers(bidIncrementTiers.map((t, j) => j === i ? { ...t, increment: parseInt(e.target.value) || 0 } : t)) }) }), _jsx(Row, { centered: true, className: "col-span-2", padding: "b-xs", children: _jsx(Button, { variant: "ghost", type: "button", disabled: bidIncrementTiers.length <= 1, onClick: () => setBidIncrementTiers(bidIncrementTiers.filter((_, j) => j !== i)), "aria-label": "Remove tier", children: "\u00D7" }) })] }, i));
|
|
773
789
|
}), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setBidIncrementTiers([
|
|
@@ -107,7 +107,7 @@ export declare const SITE_SETTINGS_TABS: readonly [{
|
|
|
107
107
|
readonly description: "Which listing types sellers may create, and their defaults.";
|
|
108
108
|
readonly keywords: ["listing types", "auctions on", "enable", "categories"];
|
|
109
109
|
}];
|
|
110
|
-
export declare const SITE_SETTINGS_TAB_IDS: ("about" | "shipping" | "
|
|
110
|
+
export declare const SITE_SETTINGS_TAB_IDS: ("about" | "shipping" | "notifications" | "contact" | "auction" | "seo" | "listings" | "appearance" | "emi" | "gst" | "watermark" | "integrations" | "limits" | "announcement" | "whatsapp" | "branding" | "themes" | "fees" | "legal" | "procurement")[];
|
|
111
111
|
/**
|
|
112
112
|
* The union `?tab=` is validated against.
|
|
113
113
|
*
|