@mohasinac/appkit 4.41.0 → 4.41.1
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/features/shell/SectionForm.js +44 -5
- package/package.json +2 -2
- package/dist/_internal/server/features/classified/actions.d.ts +0 -12
- package/dist/_internal/server/features/classified/actions.js +0 -33
- package/dist/_internal/server/features/digital-code/actions.d.ts +0 -12
- package/dist/_internal/server/features/digital-code/actions.js +0 -33
- package/dist/_internal/server/features/homepage/data.d.ts +0 -18
- package/dist/_internal/server/features/homepage/data.js +0 -70
- package/dist/_internal/server/features/live/actions.d.ts +0 -6
- package/dist/_internal/server/features/live/actions.js +0 -27
- package/dist/_internal/server/features/messages/actions.d.ts +0 -6
- package/dist/_internal/server/features/messages/actions.js +0 -6
- package/dist/_internal/server/features/messages/data.d.ts +0 -10
- package/dist/_internal/server/features/messages/data.js +0 -24
- package/dist/_internal/server/features/messages/index.d.ts +0 -2
- package/dist/_internal/server/features/messages/index.js +0 -2
- package/dist/_internal/server/jobs/core/testerSandboxRefresh.d.ts +0 -12
- package/dist/_internal/server/jobs/core/testerSandboxRefresh.js +0 -112
- package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/testerSandboxRefresh.js +0 -2
- package/dist/_internal/shared/features/homepage/section-gate.d.ts +0 -14
- package/dist/_internal/shared/features/homepage/section-gate.js +0 -51
- package/dist/_internal/shared/features/lottery/config-form.d.ts +0 -58
- package/dist/_internal/shared/features/lottery/config-form.js +0 -71
- package/dist/client/api/useFeatureFlags.d.ts +0 -22
- package/dist/client/api/useFeatureFlags.js +0 -27
- package/dist/features/account/address-validation.d.ts +0 -20
- package/dist/features/account/address-validation.js +0 -35
- package/dist/features/account/components/ChatList.d.ts +0 -14
- package/dist/features/account/components/ChatList.js +0 -9
- package/dist/features/account/components/ChatWindow.d.ts +0 -17
- package/dist/features/account/components/ChatWindow.js +0 -6
- package/dist/features/account/components/MessagesView.d.ts +0 -16
- package/dist/features/account/components/MessagesView.js +0 -5
- package/dist/features/account/components/UserOffersView.d.ts +0 -10
- package/dist/features/account/components/UserOffersView.js +0 -5
- package/dist/features/account/constants/addresses.d.ts +0 -13
- package/dist/features/account/constants/addresses.js +0 -43
- package/dist/features/account/hooks/useAddressForm.d.ts +0 -24
- package/dist/features/account/hooks/useAddressForm.js +0 -58
- package/dist/features/admin/actions/chat-actions.d.ts +0 -29
- package/dist/features/admin/actions/chat-actions.js +0 -101
- package/dist/features/admin/components/AdminFeatureFlagsView.d.ts +0 -9
- package/dist/features/admin/components/AdminFeatureFlagsView.js +0 -109
- package/dist/features/admin/components/AdminSiteView.d.ts +0 -10
- package/dist/features/admin/components/AdminSiteView.js +0 -52
- package/dist/features/admin/hooks/useChat.d.ts +0 -24
- package/dist/features/admin/hooks/useChat.js +0 -100
- package/dist/features/admin/permission-map.d.ts +0 -3
- package/dist/features/admin/permission-map.js +0 -26
- package/dist/features/admin/repository/chat.repository.d.ts +0 -50
- package/dist/features/admin/repository/chat.repository.js +0 -223
- package/dist/features/auth/actions/password-change-otp-actions.d.ts +0 -18
- package/dist/features/auth/actions/password-change-otp-actions.js +0 -88
- package/dist/features/auth/actions/realtime-token-actions.d.ts +0 -11
- package/dist/features/auth/actions/realtime-token-actions.js +0 -38
- package/dist/features/auth/password-change-otp.d.ts +0 -34
- package/dist/features/auth/password-change-otp.js +0 -56
- package/dist/features/classified/components/ClassifiedContactSellerPanel.d.ts +0 -12
- package/dist/features/classified/components/ClassifiedContactSellerPanel.js +0 -49
- package/dist/features/events/api/route.d.ts +0 -12
- package/dist/features/events/api/route.js +0 -90
- package/dist/features/faq/api/route.d.ts +0 -11
- package/dist/features/faq/api/route.js +0 -52
- package/dist/features/faq/hooks/useFAQs.d.ts +0 -22
- package/dist/features/faq/hooks/useFAQs.js +0 -41
- package/dist/features/media/upload/video-poster.test.d.ts +0 -1
- package/dist/features/media/upload/video-poster.test.js +0 -42
- package/dist/features/messages/actions/index.d.ts +0 -2
- package/dist/features/messages/actions/index.js +0 -2
- package/dist/features/messages/actions/messages-actions.d.ts +0 -15
- package/dist/features/messages/actions/messages-actions.js +0 -33
- package/dist/features/messages/actions/ping-rtdb.d.ts +0 -2
- package/dist/features/messages/actions/ping-rtdb.js +0 -26
- package/dist/features/messages/hooks/useConversation.d.ts +0 -22
- package/dist/features/messages/hooks/useConversation.js +0 -155
- package/dist/features/messages/hooks/useConversations.d.ts +0 -15
- package/dist/features/messages/hooks/useConversations.js +0 -104
- package/dist/features/messages/index.d.ts +0 -6
- package/dist/features/messages/index.js +0 -4
- package/dist/features/messages/realtime.d.ts +0 -32
- package/dist/features/messages/realtime.js +0 -39
- package/dist/features/messages/repository/conversations.repository.d.ts +0 -71
- package/dist/features/messages/repository/conversations.repository.js +0 -284
- package/dist/features/messages/schemas/firestore.d.ts +0 -34
- package/dist/features/messages/schemas/firestore.js +0 -16
- package/dist/features/messages/schemas/index.d.ts +0 -177
- package/dist/features/messages/schemas/index.js +0 -35
- package/dist/features/messages/server.d.ts +0 -6
- package/dist/features/messages/server.js +0 -6
- package/dist/features/products/components/MakeOfferForm.d.ts +0 -20
- package/dist/features/products/components/MakeOfferForm.js +0 -9
- package/dist/features/reviews/api/route.d.ts +0 -21
- package/dist/features/reviews/api/route.js +0 -174
- package/dist/features/seller/api/offers/route.d.ts +0 -17
- package/dist/features/seller/api/offers/route.js +0 -63
- package/dist/features/seller/components/SellerAuctionsView.d.ts +0 -9
- package/dist/features/seller/components/SellerAuctionsView.js +0 -113
- package/dist/features/seller/components/SellerOffersPanel.d.ts +0 -21
- package/dist/features/seller/components/SellerOffersPanel.js +0 -160
- package/dist/features/seller/components/SellerPreOrdersView.d.ts +0 -6
- package/dist/features/seller/components/SellerPreOrdersView.js +0 -148
- package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +0 -6
- package/dist/features/seller/components/SellerPrizeDrawsView.js +0 -152
- package/dist/features/seller/permission-map.d.ts +0 -5
- package/dist/features/seller/permission-map.js +0 -17
- package/dist/features/shell/StepForm.d.ts +0 -80
- package/dist/features/shell/StepForm.js +0 -136
- package/dist/features/stores/api/route.d.ts +0 -12
- package/dist/features/stores/api/route.js +0 -110
- package/dist/features/tester/seed-data/authored/account-auth__testing-program--admin.d.ts +0 -2
- package/dist/features/tester/seed-data/authored/account-auth__testing-program--admin.js +0 -33
- package/dist/features/tester/seed-data/authored/account-auth__testing-program.d.ts +0 -2
- package/dist/features/tester/seed-data/authored/account-auth__testing-program.js +0 -138
- package/dist/features/tester/seed-data/bids-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/bids-tester-seed-data.js +0 -37
- package/dist/features/tester/seed-data/blog-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/blog-tester-seed-data.js +0 -40
- package/dist/features/tester/seed-data/carts-tester-seed-data.d.ts +0 -3
- package/dist/features/tester/seed-data/carts-tester-seed-data.js +0 -70
- package/dist/features/tester/seed-data/categories-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/categories-tester-seed-data.js +0 -218
- package/dist/features/tester/seed-data/coupons-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/coupons-tester-seed-data.js +0 -76
- package/dist/features/tester/seed-data/events-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/events-tester-seed-data.js +0 -193
- package/dist/features/tester/seed-data/offers-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/offers-tester-seed-data.js +0 -191
- package/dist/features/tester/seed-data/orders-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/orders-tester-seed-data.js +0 -329
- package/dist/features/tester/seed-data/products-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/products-tester-seed-data.js +0 -815
- package/dist/features/tester/seed-data/stores-tester-seed-data.d.ts +0 -2
- package/dist/features/tester/seed-data/stores-tester-seed-data.js +0 -79
- package/dist/features/wishlist/components/WishlistToggleButton.d.ts +0 -12
- package/dist/features/wishlist/components/WishlistToggleButton.js +0 -36
- package/dist/monitoring/analytics.d.ts +0 -80
- package/dist/monitoring/analytics.js +0 -176
- package/dist/next/middleware/pii-redactor.d.ts +0 -32
- package/dist/next/middleware/pii-redactor.js +0 -84
- package/dist/providers/db-firebase/realtime.d.ts +0 -42
- package/dist/providers/db-firebase/realtime.js +0 -138
- package/dist/security/rbac/Can.d.ts +0 -31
- package/dist/security/rbac/Can.js +0 -22
- package/dist/security/rbac/default-roles.d.ts +0 -2
- package/dist/security/rbac/default-roles.js +0 -83
- package/dist/security/rbac/hook.d.ts +0 -20
- package/dist/security/rbac/hook.js +0 -30
- package/dist/security/rbac/index.d.ts +0 -8
- package/dist/security/rbac/index.js +0 -6
- package/dist/security/rbac/middleware.d.ts +0 -51
- package/dist/security/rbac/middleware.js +0 -51
- package/dist/security/rbac/resolver.d.ts +0 -5
- package/dist/security/rbac/resolver.js +0 -38
- package/dist/security/rbac/server.d.ts +0 -24
- package/dist/security/rbac/server.js +0 -42
- package/dist/security/rbac/types.d.ts +0 -22
- package/dist/security/rbac/types.js +0 -2
- package/dist/seed/conversations-seed-data.d.ts +0 -2
- package/dist/seed/conversations-seed-data.js +0 -292
- package/dist/utils/filter.helper.d.ts +0 -18
- package/dist/utils/filter.helper.js +0 -21
- package/dist/utils/pagination.helper.d.ts +0 -23
- package/dist/utils/pagination.helper.js +0 -24
- package/dist/utils/search-tokens.d.ts +0 -2
- package/dist/utils/search-tokens.js +0 -21
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* WHY: `LotteryAdminEditView` rendered `<Form>` with no schema. A lottery
|
|
3
|
-
* config is priced money: `uniformPrice` was
|
|
4
|
-
* `Math.round(parseFloat(x) * 100) / 100 || 0`, which turns any
|
|
5
|
-
* unparseable input into **zero** rather than an error — so a typo in the
|
|
6
|
-
* price box published a free lottery.
|
|
7
|
-
*
|
|
8
|
-
* `slots` is the other half: each row carries a `slotNumber`, a name and
|
|
9
|
-
* a price, and a duplicate slot number makes two buyers think they own
|
|
10
|
-
* the same slot.
|
|
11
|
-
*
|
|
12
|
-
* WHAT: The config contract.
|
|
13
|
-
*
|
|
14
|
-
* @tag domain:lottery
|
|
15
|
-
* @tag layer:schema
|
|
16
|
-
* @tag pattern:none
|
|
17
|
-
* @tag access:isomorphic
|
|
18
|
-
* @tag consumers:LotteryAdminEditView
|
|
19
|
-
* @tag sideEffects:none
|
|
20
|
-
*/
|
|
21
|
-
import { z } from "zod";
|
|
22
|
-
import { annotate } from "../../../../features/shell/field-ui-meta";
|
|
23
|
-
const slotSchema = z.object({
|
|
24
|
-
slotNumber: z.coerce.number().int().min(1, "Slot numbers start at 1."),
|
|
25
|
-
name: z.string().trim().max(120).optional(),
|
|
26
|
-
price: z.coerce.number().min(0, "A slot price cannot be negative.").optional(),
|
|
27
|
-
image: z.string().trim().optional(),
|
|
28
|
-
});
|
|
29
|
-
export const lotteryConfigFormSchema = z
|
|
30
|
-
.object({
|
|
31
|
-
pricingMode: annotate(z.enum(["uniform", "variable"]), {
|
|
32
|
-
section: "pricing", sectionLabel: "Pricing", sectionRequired: true, quick: true, order: 1, row: "pair",
|
|
33
|
-
}),
|
|
34
|
-
/*
|
|
35
|
-
* 🛑 Coerced with a real error, NOT `|| 0`. The previous
|
|
36
|
-
* `parseFloat(x) || 0` silently turned "12,00" or "twelve" into a free
|
|
37
|
-
* lottery — the failure was indistinguishable from deliberately pricing
|
|
38
|
-
* it at zero.
|
|
39
|
-
*/
|
|
40
|
-
uniformPrice: annotate(z.coerce
|
|
41
|
-
.number({ invalid_type_error: "Enter the slot price as a number." })
|
|
42
|
-
.min(0, "A price cannot be negative.")
|
|
43
|
-
.max(10000000, "That looks like a typo.")
|
|
44
|
-
.optional(), { section: "pricing", order: 2, row: "pair", kind: "number" }),
|
|
45
|
-
slots: annotate(z.array(slotSchema).min(1, "A lottery needs at least one slot.").max(1000), {
|
|
46
|
-
section: "slots", sectionLabel: "Slots", sectionRequired: true, order: 1, row: "full", kind: "list",
|
|
47
|
-
}),
|
|
48
|
-
})
|
|
49
|
-
.superRefine((v, ctx) => {
|
|
50
|
-
// Uniform pricing with no price is the free-lottery case the `|| 0` used
|
|
51
|
-
// to create silently.
|
|
52
|
-
if (v.pricingMode === "uniform" && (v.uniformPrice === undefined || v.uniformPrice <= 0)) {
|
|
53
|
-
ctx.addIssue({
|
|
54
|
-
code: z.ZodIssueCode.custom,
|
|
55
|
-
path: ["uniformPrice"],
|
|
56
|
-
message: "Set a slot price above zero, or switch to variable pricing.",
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
// Two buyers cannot own the same slot number.
|
|
60
|
-
const seen = new Set();
|
|
61
|
-
for (const [i, s] of v.slots.entries()) {
|
|
62
|
-
if (seen.has(s.slotNumber)) {
|
|
63
|
-
ctx.addIssue({
|
|
64
|
-
code: z.ZodIssueCode.custom,
|
|
65
|
-
path: ["slots", i, "slotNumber"],
|
|
66
|
-
message: `Slot ${s.slotNumber} appears more than once.`,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
seen.add(s.slotNumber);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Consumer app's flag names aren't known to appkit (they're project-specific,
|
|
3
|
-
* e.g. "PAYOUTS" | "COUPONS" | ...) — this stays a loose string-keyed map so
|
|
4
|
-
* appkit doesn't hardcode a consumer's roadmap. Cast the result where a
|
|
5
|
-
* consumer wants a narrower, project-specific union.
|
|
6
|
-
*/
|
|
7
|
-
export type FeatureFlagState = Record<string, boolean>;
|
|
8
|
-
/**
|
|
9
|
-
* Client-safe feature-flag check — `getFlag()`/`withFeatureGuard` are
|
|
10
|
-
* server-only, so `"use client"` components have no way to know a flag is
|
|
11
|
-
* off before firing a request against its (guarded) API. This hook fetches
|
|
12
|
-
* the public flag snapshot once (cached for the query's lifetime) so a
|
|
13
|
-
* component can skip the fetch and skip rendering entirely when disabled,
|
|
14
|
-
* instead of eating a 404 from the guarded route.
|
|
15
|
-
*
|
|
16
|
-
* `flags` defaults to an empty object while loading, so callers should treat
|
|
17
|
-
* a missing key as `false` (fail-closed) rather than assuming it's enabled.
|
|
18
|
-
*/
|
|
19
|
-
export declare function useFeatureFlags(): {
|
|
20
|
-
flags: FeatureFlagState;
|
|
21
|
-
isLoading: boolean;
|
|
22
|
-
};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useApiQuery } from "./useApiQuery";
|
|
3
|
-
import { apiClient } from "../../http";
|
|
4
|
-
import { API_ENDPOINTS } from "../../constants/api-endpoints";
|
|
5
|
-
/**
|
|
6
|
-
* Client-safe feature-flag check — `getFlag()`/`withFeatureGuard` are
|
|
7
|
-
* server-only, so `"use client"` components have no way to know a flag is
|
|
8
|
-
* off before firing a request against its (guarded) API. This hook fetches
|
|
9
|
-
* the public flag snapshot once (cached for the query's lifetime) so a
|
|
10
|
-
* component can skip the fetch and skip rendering entirely when disabled,
|
|
11
|
-
* instead of eating a 404 from the guarded route.
|
|
12
|
-
*
|
|
13
|
-
* `flags` defaults to an empty object while loading, so callers should treat
|
|
14
|
-
* a missing key as `false` (fail-closed) rather than assuming it's enabled.
|
|
15
|
-
*/
|
|
16
|
-
export function useFeatureFlags() {
|
|
17
|
-
const query = useApiQuery({
|
|
18
|
-
queryKey: ["feature-flags"],
|
|
19
|
-
queryFn: () => apiClient.get(API_ENDPOINTS.CONFIG.FEATURE_FLAGS),
|
|
20
|
-
staleTime: 60000,
|
|
21
|
-
silentBackgroundFailures: true,
|
|
22
|
-
});
|
|
23
|
-
return {
|
|
24
|
-
flags: query.data ?? {},
|
|
25
|
-
isLoading: query.isLoading,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface AddressValidationFormData {
|
|
2
|
-
fullName: string;
|
|
3
|
-
phoneNumber: string;
|
|
4
|
-
pincode: string;
|
|
5
|
-
addressLine1: string;
|
|
6
|
-
addressLine2?: string;
|
|
7
|
-
landmark?: string;
|
|
8
|
-
city: string;
|
|
9
|
-
state: string;
|
|
10
|
-
addressType: string;
|
|
11
|
-
isDefault: boolean;
|
|
12
|
-
}
|
|
13
|
-
export interface AddressValidationOptions {
|
|
14
|
-
validatePhoneNumber?: (value: string) => boolean;
|
|
15
|
-
validatePostalCode?: (value: string) => boolean;
|
|
16
|
-
requiredFieldMessage?: string;
|
|
17
|
-
invalidPhoneMessage?: string;
|
|
18
|
-
invalidPostalCodeMessage?: string;
|
|
19
|
-
}
|
|
20
|
-
export declare function validateAddressForm(formData: AddressValidationFormData, options?: AddressValidationOptions): Record<string, string>;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { ERROR_MESSAGES } from "../../errors";
|
|
2
|
-
export function validateAddressForm(formData, options) {
|
|
3
|
-
const errors = {};
|
|
4
|
-
const requiredFieldMessage = options?.requiredFieldMessage ?? ERROR_MESSAGES.VALIDATION.REQUIRED_FIELD;
|
|
5
|
-
if (!formData.fullName?.trim()) {
|
|
6
|
-
errors.fullName = requiredFieldMessage;
|
|
7
|
-
}
|
|
8
|
-
if (!formData.phoneNumber?.trim()) {
|
|
9
|
-
errors.phoneNumber = requiredFieldMessage;
|
|
10
|
-
}
|
|
11
|
-
else if (options?.validatePhoneNumber &&
|
|
12
|
-
!options.validatePhoneNumber(formData.phoneNumber)) {
|
|
13
|
-
errors.phoneNumber =
|
|
14
|
-
options.invalidPhoneMessage ?? ERROR_MESSAGES.VALIDATION.INVALID_PHONE;
|
|
15
|
-
}
|
|
16
|
-
if (!formData.pincode?.trim()) {
|
|
17
|
-
errors.pincode = requiredFieldMessage;
|
|
18
|
-
}
|
|
19
|
-
else if (options?.validatePostalCode &&
|
|
20
|
-
!options.validatePostalCode(formData.pincode)) {
|
|
21
|
-
errors.pincode =
|
|
22
|
-
options.invalidPostalCodeMessage ??
|
|
23
|
-
ERROR_MESSAGES.VALIDATION.INVALID_INPUT;
|
|
24
|
-
}
|
|
25
|
-
if (!formData.addressLine1?.trim()) {
|
|
26
|
-
errors.addressLine1 = requiredFieldMessage;
|
|
27
|
-
}
|
|
28
|
-
if (!formData.city?.trim()) {
|
|
29
|
-
errors.city = requiredFieldMessage;
|
|
30
|
-
}
|
|
31
|
-
if (!formData.state?.trim()) {
|
|
32
|
-
errors.state = requiredFieldMessage;
|
|
33
|
-
}
|
|
34
|
-
return errors;
|
|
35
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export interface ChatListLabels {
|
|
3
|
-
title?: string;
|
|
4
|
-
}
|
|
5
|
-
export interface ChatListProps {
|
|
6
|
-
labels?: ChatListLabels;
|
|
7
|
-
isLoading?: boolean;
|
|
8
|
-
hasItems: boolean;
|
|
9
|
-
renderLoading?: () => React.ReactNode;
|
|
10
|
-
renderEmptyState?: () => React.ReactNode;
|
|
11
|
-
renderList: () => React.ReactNode;
|
|
12
|
-
className?: string;
|
|
13
|
-
}
|
|
14
|
-
export declare function ChatList({ labels, isLoading, hasItems, renderLoading, renderEmptyState, renderList, className, }: ChatListProps): React.JSX.Element;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Div, Heading } from "../../../ui";
|
|
3
|
-
export function ChatList({ labels = {}, isLoading = false, hasItems, renderLoading, renderEmptyState, renderList, className = "", }) {
|
|
4
|
-
return (_jsxs(Div, { className: className, children: [labels.title && (_jsx(Heading, { level: 4, className: "mb-3", weight: "semibold", children: labels.title })), isLoading
|
|
5
|
-
? (renderLoading?.() ?? null)
|
|
6
|
-
: hasItems
|
|
7
|
-
? renderList()
|
|
8
|
-
: (renderEmptyState?.() ?? null)] }));
|
|
9
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export interface ChatWindowLabels {
|
|
3
|
-
title?: string;
|
|
4
|
-
connected?: string;
|
|
5
|
-
disconnected?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface ChatWindowProps {
|
|
8
|
-
labels?: ChatWindowLabels;
|
|
9
|
-
isConnected?: boolean;
|
|
10
|
-
isLoading?: boolean;
|
|
11
|
-
error?: React.ReactNode;
|
|
12
|
-
renderLoadingIndicator?: () => React.ReactNode;
|
|
13
|
-
renderMessages: () => React.ReactNode;
|
|
14
|
-
renderInput: () => React.ReactNode;
|
|
15
|
-
className?: string;
|
|
16
|
-
}
|
|
17
|
-
export declare function ChatWindow({ labels, isConnected, isLoading, error, renderLoadingIndicator, renderMessages, renderInput, className, }: ChatWindowProps): React.JSX.Element;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Div, Heading, Row, Span } from "../../../ui";
|
|
3
|
-
const CLS_DOT_ON = "bg-success-surface";
|
|
4
|
-
export function ChatWindow({ labels = {}, isConnected = true, isLoading = false, error, renderLoadingIndicator, renderMessages, renderInput, className = "", }) {
|
|
5
|
-
return (_jsxs(Div, { className: className, children: [_jsxs(Row, { justify: "between", className: "border-b border-[var(--appkit-color-border)] mb-3", padding: "b-sm", children: [_jsxs(Row, { gap: "xs", children: [labels.title && _jsx(Heading, { level: 4, children: labels.title }), _jsx(Span, { className: `w-2 h-2 ${isConnected ? CLS_DOT_ON : "bg-[var(--appkit-color-text-faint)]"}`, rounded: "full", "aria-label": isConnected ? labels.connected : labels.disconnected })] }), isLoading && (renderLoadingIndicator?.() ?? null)] }), error ?? null, renderMessages(), renderInput()] }));
|
|
6
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export interface MessagesViewLabels {
|
|
3
|
-
title?: string;
|
|
4
|
-
selectRoom?: string;
|
|
5
|
-
backToList?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface MessagesViewProps {
|
|
8
|
-
labels?: MessagesViewLabels;
|
|
9
|
-
chatId?: string | null;
|
|
10
|
-
renderChatList?: () => React.ReactNode;
|
|
11
|
-
renderChatWindow?: () => React.ReactNode;
|
|
12
|
-
renderMobileBack?: () => React.ReactNode;
|
|
13
|
-
renderEmptyState?: () => React.ReactNode;
|
|
14
|
-
className?: string;
|
|
15
|
-
}
|
|
16
|
-
export declare function MessagesView({ labels, chatId, renderChatList, renderChatWindow, renderMobileBack, renderEmptyState, className, }: MessagesViewProps): React.JSX.Element;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Div, Heading, Span, Stack } from "../../../ui";
|
|
3
|
-
export function MessagesView({ labels = {}, chatId, renderChatList, renderChatWindow, renderMobileBack, renderEmptyState, className = "", }) {
|
|
4
|
-
return (_jsxs(Div, { layout: "grid", gap: "4", className: `grid-cols-1 md:grid-cols-[280px_1fr] xl:grid-cols-[320px_1fr] 2xl:grid-cols-[360px_1fr] h-full min-h-[600px] ${className}`, children: [_jsxs(Div, { className: chatId ? "hidden md:block" : "block", children: [labels.title && (_jsx(Heading, { level: 3, className: "mb-3", weight: "semibold", children: labels.title })), renderChatList?.()] }), chatId ? (_jsxs(Stack, { gap: "xs", children: [renderMobileBack?.(), renderChatWindow?.()] })) : (_jsx(Div, { className: "hidden md:flex text-[var(--appkit-color-text-faint)] border border-dashed border-[var(--appkit-color-border)]", align: "center", justify: "center", rounded: "xl", children: renderEmptyState?.() ?? (_jsx(Span, { children: labels.selectRoom ?? "Select a conversation" })) }))] }));
|
|
5
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { StackedViewShellProps } from "../../../ui";
|
|
3
|
-
export interface UserOffersViewLabels {
|
|
4
|
-
title?: string;
|
|
5
|
-
}
|
|
6
|
-
export interface UserOffersViewProps extends Omit<StackedViewShellProps, "sections"> {
|
|
7
|
-
labels?: UserOffersViewLabels;
|
|
8
|
-
renderTable?: () => React.ReactNode;
|
|
9
|
-
}
|
|
10
|
-
export declare function UserOffersView({ labels, renderTable, ...rest }: UserOffersViewProps): React.JSX.Element;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { StackedViewShell } from "../../../ui";
|
|
3
|
-
export function UserOffersView({ labels = {}, renderTable, ...rest }) {
|
|
4
|
-
return (_jsx(StackedViewShell, { portal: "user", ...rest, title: labels.title, sections: [renderTable?.()] }));
|
|
5
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export declare const ADDRESS_TYPES: readonly [{
|
|
2
|
-
readonly value: "home";
|
|
3
|
-
readonly label: "Home";
|
|
4
|
-
}, {
|
|
5
|
-
readonly value: "work";
|
|
6
|
-
readonly label: "Work";
|
|
7
|
-
}, {
|
|
8
|
-
readonly value: "other";
|
|
9
|
-
readonly label: "Other";
|
|
10
|
-
}];
|
|
11
|
-
export type AddressType = (typeof ADDRESS_TYPES)[number]["value"];
|
|
12
|
-
export declare const INDIAN_STATES: readonly ["Andhra Pradesh", "Arunachal Pradesh", "Assam", "Bihar", "Chhattisgarh", "Goa", "Gujarat", "Haryana", "Himachal Pradesh", "Jharkhand", "Karnataka", "Kerala", "Madhya Pradesh", "Maharashtra", "Manipur", "Meghalaya", "Mizoram", "Nagaland", "Odisha", "Punjab", "Rajasthan", "Sikkim", "Tamil Nadu", "Telangana", "Tripura", "Uttar Pradesh", "Uttarakhand", "West Bengal", "Andaman and Nicobar Islands", "Chandigarh", "Dadra and Nagar Haveli and Daman and Diu", "Delhi", "Jammu and Kashmir", "Ladakh", "Lakshadweep", "Puducherry"];
|
|
13
|
-
export type IndianState = (typeof INDIAN_STATES)[number];
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export const ADDRESS_TYPES = [
|
|
2
|
-
{ value: "home", label: "Home" },
|
|
3
|
-
{ value: "work", label: "Work" },
|
|
4
|
-
{ value: "other", label: "Other" },
|
|
5
|
-
];
|
|
6
|
-
export const INDIAN_STATES = [
|
|
7
|
-
"Andhra Pradesh",
|
|
8
|
-
"Arunachal Pradesh",
|
|
9
|
-
"Assam",
|
|
10
|
-
"Bihar",
|
|
11
|
-
"Chhattisgarh",
|
|
12
|
-
"Goa",
|
|
13
|
-
"Gujarat",
|
|
14
|
-
"Haryana",
|
|
15
|
-
"Himachal Pradesh",
|
|
16
|
-
"Jharkhand",
|
|
17
|
-
"Karnataka",
|
|
18
|
-
"Kerala",
|
|
19
|
-
"Madhya Pradesh",
|
|
20
|
-
"Maharashtra",
|
|
21
|
-
"Manipur",
|
|
22
|
-
"Meghalaya",
|
|
23
|
-
"Mizoram",
|
|
24
|
-
"Nagaland",
|
|
25
|
-
"Odisha",
|
|
26
|
-
"Punjab",
|
|
27
|
-
"Rajasthan",
|
|
28
|
-
"Sikkim",
|
|
29
|
-
"Tamil Nadu",
|
|
30
|
-
"Telangana",
|
|
31
|
-
"Tripura",
|
|
32
|
-
"Uttar Pradesh",
|
|
33
|
-
"Uttarakhand",
|
|
34
|
-
"West Bengal",
|
|
35
|
-
"Andaman and Nicobar Islands",
|
|
36
|
-
"Chandigarh",
|
|
37
|
-
"Dadra and Nagar Haveli and Daman and Diu",
|
|
38
|
-
"Delhi",
|
|
39
|
-
"Jammu and Kashmir",
|
|
40
|
-
"Ladakh",
|
|
41
|
-
"Lakshadweep",
|
|
42
|
-
"Puducherry",
|
|
43
|
-
];
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export interface AddressFormStateData {
|
|
2
|
-
fullName: string;
|
|
3
|
-
phoneNumber: string;
|
|
4
|
-
pincode: string;
|
|
5
|
-
addressLine1: string;
|
|
6
|
-
addressLine2: string;
|
|
7
|
-
landmark: string;
|
|
8
|
-
city: string;
|
|
9
|
-
state: string;
|
|
10
|
-
addressType: string;
|
|
11
|
-
isDefault: boolean;
|
|
12
|
-
}
|
|
13
|
-
interface UseAddressFormResult {
|
|
14
|
-
formData: AddressFormStateData;
|
|
15
|
-
errors: Record<string, string>;
|
|
16
|
-
handleChange: (field: keyof AddressFormStateData, value: string | boolean) => void;
|
|
17
|
-
validate: () => boolean;
|
|
18
|
-
reset: (data?: Partial<AddressFormStateData>) => void;
|
|
19
|
-
setFormData: React.Dispatch<React.SetStateAction<AddressFormStateData>>;
|
|
20
|
-
}
|
|
21
|
-
export declare function useAddressForm(initialData?: Partial<AddressFormStateData>, options?: {
|
|
22
|
-
validateFn?: (data: AddressFormStateData) => Record<string, string>;
|
|
23
|
-
}): UseAddressFormResult;
|
|
24
|
-
export {};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useCallback, useState } from "react";
|
|
3
|
-
const DEFAULT_FORM_DATA = {
|
|
4
|
-
fullName: "",
|
|
5
|
-
phoneNumber: "",
|
|
6
|
-
pincode: "",
|
|
7
|
-
addressLine1: "",
|
|
8
|
-
addressLine2: "",
|
|
9
|
-
landmark: "",
|
|
10
|
-
city: "",
|
|
11
|
-
state: "",
|
|
12
|
-
addressType: "home",
|
|
13
|
-
isDefault: false,
|
|
14
|
-
};
|
|
15
|
-
function defaultValidate(data) {
|
|
16
|
-
const errors = {};
|
|
17
|
-
if (!data.fullName.trim())
|
|
18
|
-
errors.fullName = "Full name is required";
|
|
19
|
-
if (!data.phoneNumber.trim())
|
|
20
|
-
errors.phoneNumber = "Phone number is required";
|
|
21
|
-
if (!data.addressLine1.trim())
|
|
22
|
-
errors.addressLine1 = "Address line 1 is required";
|
|
23
|
-
if (!data.city.trim())
|
|
24
|
-
errors.city = "City is required";
|
|
25
|
-
if (!data.state.trim())
|
|
26
|
-
errors.state = "State is required";
|
|
27
|
-
if (!data.pincode.trim())
|
|
28
|
-
errors.pincode = "Pincode is required";
|
|
29
|
-
return errors;
|
|
30
|
-
}
|
|
31
|
-
export function useAddressForm(initialData = {}, options) {
|
|
32
|
-
const [formData, setFormData] = useState({
|
|
33
|
-
...DEFAULT_FORM_DATA,
|
|
34
|
-
...initialData,
|
|
35
|
-
});
|
|
36
|
-
const [errors, setErrors] = useState({});
|
|
37
|
-
const validateFn = options?.validateFn ?? defaultValidate;
|
|
38
|
-
const handleChange = useCallback((field, value) => {
|
|
39
|
-
setFormData((prev) => ({ ...prev, [field]: value }));
|
|
40
|
-
if (errors[field]) {
|
|
41
|
-
setErrors((prev) => {
|
|
42
|
-
const next = { ...prev };
|
|
43
|
-
delete next[field];
|
|
44
|
-
return next;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}, [errors]);
|
|
48
|
-
const validate = useCallback(() => {
|
|
49
|
-
const newErrors = validateFn(formData);
|
|
50
|
-
setErrors(newErrors);
|
|
51
|
-
return Object.keys(newErrors).length === 0;
|
|
52
|
-
}, [formData, validateFn]);
|
|
53
|
-
const reset = useCallback((data = {}) => {
|
|
54
|
-
setFormData({ ...DEFAULT_FORM_DATA, ...data });
|
|
55
|
-
setErrors({});
|
|
56
|
-
}, []);
|
|
57
|
-
return { formData, errors, handleChange, validate, reset, setFormData };
|
|
58
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat Domain Actions — appkit
|
|
3
|
-
*
|
|
4
|
-
* Pure async functions for buyer↔seller chat. No auth, no rate-limit.
|
|
5
|
-
* Accept userId as explicit parameter. Called by letitrip thin wrappers.
|
|
6
|
-
*
|
|
7
|
-
* chatEnabled must be passed from the consumer (e.g. FEATURE_FLAGS.CHAT_ENABLED)
|
|
8
|
-
* rather than reading it from appkit to keep market config in letitrip.
|
|
9
|
-
*/
|
|
10
|
-
import type { ChatRoomDocument } from "../repository/chat.repository";
|
|
11
|
-
export interface ChatRoomsResult {
|
|
12
|
-
rooms: ChatRoomDocument[];
|
|
13
|
-
}
|
|
14
|
-
export interface CreateRoomInput {
|
|
15
|
-
orderId: string;
|
|
16
|
-
ownerId: string;
|
|
17
|
-
}
|
|
18
|
-
export interface CreateRoomResult {
|
|
19
|
-
room: ChatRoomDocument;
|
|
20
|
-
}
|
|
21
|
-
export declare function getChatRooms(userId: string, chatEnabled: boolean): Promise<ChatRoomsResult>;
|
|
22
|
-
export declare function createOrGetChatRoom(userId: string, chatEnabled: boolean, input: CreateRoomInput): Promise<CreateRoomResult>;
|
|
23
|
-
export declare function sendChatMessage(userId: string, chatId: string, message: string): Promise<{
|
|
24
|
-
messageId: string;
|
|
25
|
-
timestamp: number;
|
|
26
|
-
}>;
|
|
27
|
-
export declare function deleteChatRoom(userId: string, chatId: string): Promise<{
|
|
28
|
-
deleted: boolean;
|
|
29
|
-
}>;
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chat Domain Actions — appkit
|
|
3
|
-
*
|
|
4
|
-
* Pure async functions for buyer↔seller chat. No auth, no rate-limit.
|
|
5
|
-
* Accept userId as explicit parameter. Called by letitrip thin wrappers.
|
|
6
|
-
*
|
|
7
|
-
* chatEnabled must be passed from the consumer (e.g. FEATURE_FLAGS.CHAT_ENABLED)
|
|
8
|
-
* rather than reading it from appkit to keep market config in letitrip.
|
|
9
|
-
*/
|
|
10
|
-
import { chatRepository } from "../repository/chat.repository";
|
|
11
|
-
import { orderRepository } from "../../orders/repository/orders.repository";
|
|
12
|
-
import { userRepository } from "../../auth/repository/user.repository";
|
|
13
|
-
import { getAdminRealtimeDb } from "../../../providers/db-firebase/index";
|
|
14
|
-
import { AuthorizationError, NotFoundError, ValidationError, } from "../../../errors/index";
|
|
15
|
-
import { ERROR_MESSAGES } from "../../../errors/messages";
|
|
16
|
-
import { serverLogger } from "../../../monitoring/index";
|
|
17
|
-
import { normalizeError } from "../../../errors/normalize";
|
|
18
|
-
export async function getChatRooms(userId, chatEnabled) {
|
|
19
|
-
if (!chatEnabled)
|
|
20
|
-
throw new AuthorizationError("Chat is temporarily unavailable.");
|
|
21
|
-
const rooms = await chatRepository.listForUser(userId);
|
|
22
|
-
return { rooms };
|
|
23
|
-
}
|
|
24
|
-
export async function createOrGetChatRoom(userId, chatEnabled, input) {
|
|
25
|
-
if (!chatEnabled)
|
|
26
|
-
throw new AuthorizationError("Chat is temporarily unavailable.");
|
|
27
|
-
const { orderId, ownerId } = input;
|
|
28
|
-
const order = await orderRepository.findById(orderId);
|
|
29
|
-
if (!order)
|
|
30
|
-
throw new NotFoundError(ERROR_MESSAGES.ORDER.NOT_FOUND);
|
|
31
|
-
if (order.userId !== userId && ownerId !== userId)
|
|
32
|
-
throw new AuthorizationError(ERROR_MESSAGES.CHAT.NOT_AUTHORIZED);
|
|
33
|
-
const buyerId = order.userId;
|
|
34
|
-
const existing = await chatRepository.findRoom(buyerId, ownerId, orderId);
|
|
35
|
-
if (existing) {
|
|
36
|
-
const deletedBy = existing.deletedBy ?? [];
|
|
37
|
-
if (deletedBy.includes(userId)) {
|
|
38
|
-
const reopened = deletedBy.filter((id) => id !== userId);
|
|
39
|
-
await chatRepository.update(existing.id, { deletedBy: reopened });
|
|
40
|
-
return { room: { ...existing, deletedBy: reopened } };
|
|
41
|
-
}
|
|
42
|
-
return { room: existing };
|
|
43
|
-
}
|
|
44
|
-
const [buyer, owner] = await Promise.all([
|
|
45
|
-
userRepository.findById(buyerId),
|
|
46
|
-
userRepository.findById(ownerId),
|
|
47
|
-
]);
|
|
48
|
-
const room = await chatRepository.create({
|
|
49
|
-
buyerId,
|
|
50
|
-
ownerId,
|
|
51
|
-
orderId,
|
|
52
|
-
productId: order.productId,
|
|
53
|
-
productTitle: order.productTitle,
|
|
54
|
-
buyerName: buyer?.displayName ?? "Buyer",
|
|
55
|
-
ownerName: owner?.displayName ?? "Seller",
|
|
56
|
-
participantIds: [buyerId, ownerId],
|
|
57
|
-
});
|
|
58
|
-
serverLogger.info("createOrGetChatRoom: room created", { userId, orderId });
|
|
59
|
-
return { room };
|
|
60
|
-
}
|
|
61
|
-
export async function sendChatMessage(userId, chatId, message) {
|
|
62
|
-
if (!chatId?.trim())
|
|
63
|
-
throw new ValidationError("chatId is required");
|
|
64
|
-
if (!message?.trim())
|
|
65
|
-
throw new ValidationError("message is required");
|
|
66
|
-
const room = await chatRepository.findById(chatId);
|
|
67
|
-
if (!room)
|
|
68
|
-
throw new NotFoundError("Chat room not found");
|
|
69
|
-
if (!(room.participantIds ?? []).includes(userId))
|
|
70
|
-
throw new AuthorizationError("Not a participant of this chat");
|
|
71
|
-
const rtdb = getAdminRealtimeDb();
|
|
72
|
-
const msgRef = rtdb.ref(`/chat/${chatId}/messages`).push();
|
|
73
|
-
const id = msgRef.key;
|
|
74
|
-
const userName = userId === room.buyerId
|
|
75
|
-
? (room.buyerName ?? "Buyer")
|
|
76
|
-
: userId === room.ownerId
|
|
77
|
-
? (room.ownerName ?? "Seller")
|
|
78
|
-
: (room.buyerName ?? "Member");
|
|
79
|
-
await msgRef.set({ userId, userName, message, timestamp: Date.now() });
|
|
80
|
-
chatRepository.updateLastMessage(chatId, message).catch((err) => {
|
|
81
|
-
serverLogger.warn("Failed to update chat lastMessage", {
|
|
82
|
-
chatId,
|
|
83
|
-
error: normalizeError(err).message,
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
serverLogger.debug("sendChatMessage", { userId, chatId });
|
|
87
|
-
return { messageId: id, timestamp: Date.now() };
|
|
88
|
-
}
|
|
89
|
-
export async function deleteChatRoom(userId, chatId) {
|
|
90
|
-
if (!chatId?.trim())
|
|
91
|
-
throw new ValidationError("chatId is required");
|
|
92
|
-
const room = await chatRepository.findById(chatId);
|
|
93
|
-
if (!room)
|
|
94
|
-
throw new NotFoundError("Chat room not found");
|
|
95
|
-
const deletedBy = room.deletedBy ?? [];
|
|
96
|
-
if (!deletedBy.includes(userId)) {
|
|
97
|
-
await chatRepository.update(chatId, { deletedBy: [...deletedBy, userId] });
|
|
98
|
-
}
|
|
99
|
-
serverLogger.info("deleteChatRoom: soft-deleted", { userId, chatId });
|
|
100
|
-
return { deleted: true };
|
|
101
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { StackedViewShellProps } from "../../../ui";
|
|
3
|
-
export interface AdminFeatureFlagsViewProps extends Omit<StackedViewShellProps, "sections"> {
|
|
4
|
-
labels?: {
|
|
5
|
-
title?: string;
|
|
6
|
-
};
|
|
7
|
-
renderFlags?: () => React.ReactNode;
|
|
8
|
-
}
|
|
9
|
-
export declare function AdminFeatureFlagsView({ labels, renderFlags, ...rest }: AdminFeatureFlagsViewProps): React.JSX.Element;
|