@vtex/faststore-plugin-buyer-portal 1.1.1 → 1.1.3
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/.github/workflows/ci.yml +1 -1
- package/.github/workflows/release.yaml +1 -1
- package/CHANGELOG.md +3 -0
- package/package.json +4 -4
- package/plugin.config.js +4 -6
- package/public/buyer-portal-icons.svg +15 -0
- package/src/features/addresses/clients/AddressesClient.ts +24 -11
- package/src/features/addresses/clients/RecipientsClient.ts +110 -0
- package/src/features/addresses/components/AddRecipientsDrawer/AddRecipientsDrawer.tsx +87 -0
- package/src/features/addresses/components/AddressDropdownMenu/AddressDropdownMenu.tsx +7 -3
- package/src/features/addresses/components/AddressRecipientsList/AddressRecipientsList.tsx +238 -0
- package/src/features/addresses/components/AddressRecipientsList/address-recipients-list.scss +57 -0
- package/src/features/addresses/components/CreateAddressDrawer/CreateAddressDrawer.tsx +1 -3
- package/src/features/addresses/components/DeleteRecipientAddressDrawer/DeleteRecipientAddressDrawer.tsx +112 -0
- package/src/features/addresses/components/EditRecipientAddressDrawer/EditRecipientAddressDrawer.tsx +174 -0
- package/src/features/addresses/components/EditRecipientAddressDrawer/edit-recipient-address-drawer.scss +30 -0
- package/src/features/addresses/components/RecipientsForm/RecipientItem/RecipientItem.tsx +64 -0
- package/src/features/addresses/components/RecipientsForm/RecipientItem/recipient-item.scss +32 -0
- package/src/features/addresses/components/RecipientsForm/RecipientsForm.tsx +39 -54
- package/src/features/addresses/components/RecipientsForm/recipients-form.scss +8 -9
- package/src/features/addresses/components/index.ts +1 -1
- package/src/features/addresses/hooks/useAddRecipientsToAddress.ts +27 -0
- package/src/features/addresses/hooks/useDeleteRecipientAddress.ts +30 -0
- package/src/features/addresses/hooks/useEditRecipientsToAddress.ts +27 -0
- package/src/features/addresses/hooks/useSearchAddressRecipients.ts +26 -0
- package/src/features/addresses/layouts/AddressDetailsLayout/AddressDetailsLayout.tsx +90 -16
- package/src/features/addresses/layouts/AddressDetailsLayout/address-details-layout.scss +10 -0
- package/src/features/addresses/layouts/AddressesLayout/AddressesLayout.tsx +3 -1
- package/src/features/addresses/layouts/AddressesLayout/addresses-layout.scss +1 -0
- package/src/features/addresses/services/recipients/add-address-recipients.service.ts +29 -0
- package/src/features/addresses/services/recipients/delete-address-recipients.service.ts +24 -0
- package/src/features/addresses/services/recipients/edit-address-recipients.service.ts +28 -0
- package/src/features/addresses/services/recipients/get-address-recipients.service.ts +29 -0
- package/src/features/addresses/types/AddressData.ts +30 -0
- package/src/features/addresses/types/index.ts +1 -0
- package/src/features/buying-policies/clients/BuyingPoliciesClient.ts +26 -14
- package/src/features/collections/clients/CollectionsClient.ts +101 -0
- package/src/features/collections/components/AddCollectionsDrawer/AddCollectionsDrawer.tsx +143 -0
- package/src/features/collections/components/AddCollectionsDrawer/add-collections-drawer.scss +58 -0
- package/src/features/collections/components/CollectionsTable/CollectionsTable.tsx +94 -0
- package/src/features/collections/components/CollectionsTable/collections-table.scss +101 -0
- package/src/features/collections/components/RemoveCollectionDrawer/RemoveCollectionDrawer.tsx +75 -0
- package/src/features/collections/components/RemoveCollectionDrawer/remove-collection-drawer.scss +15 -0
- package/src/features/collections/components/index.tsx +5 -0
- package/src/features/collections/components/table/AddCollectionsDrawerTable.tsx +110 -0
- package/src/features/collections/components/table/add-collections-drawer-table.scss +66 -0
- package/src/features/collections/hooks/useAddCollectionsToScope.ts +23 -0
- package/src/features/collections/hooks/useGetCollectionsFromContract.ts +24 -0
- package/src/features/collections/hooks/useGetCollectionsFromScope.ts +27 -0
- package/src/features/collections/hooks/useRemoveCollectionsFromScope.ts +26 -0
- package/src/features/collections/layouts/CollectionsLayout/CollectionsLayout.tsx +153 -0
- package/src/features/collections/layouts/CollectionsLayout/collections-layout.scss +92 -0
- package/src/features/collections/layouts/index.ts +4 -0
- package/src/features/collections/services/add-collections-to-scope.service.ts +15 -0
- package/src/features/collections/services/get-collections-from-contract.service.ts +9 -0
- package/src/features/collections/services/get-collections-from-scope.service.ts +32 -0
- package/src/features/collections/services/remove-collections-from-scope.ts +7 -0
- package/src/features/collections/types/index.ts +20 -0
- package/src/features/shared/components/BasicDrawer/BasicDrawer.tsx +3 -0
- package/src/features/shared/components/BasicDrawer/BasicDrawerButton.tsx +4 -3
- package/src/features/shared/components/BasicDrawer/basic-drawer.scss +7 -5
- package/src/features/shared/components/Tab/Tab.tsx +13 -3
- package/src/features/shared/components/Table/TableRow/TableRow.tsx +7 -4
- package/src/features/shared/components/TextHighlight/TextHighlight.tsx +25 -0
- package/src/features/shared/hooks/usePageItems.ts +1 -7
- package/src/features/shared/utils/phoneNumber.ts +18 -0
- package/src/pages/address-details.tsx +51 -6
- package/src/pages/collections.tsx +107 -0
- package/src/themes/layouts.scss +3 -0
- package/src/features/addresses/components/RecipientsDrawer/RecipientsDrawer.tsx +0 -39
package/.github/workflows/ci.yml
CHANGED
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vtex/faststore-plugin-buyer-portal",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "A plugin for faststore with buyer portal",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@types/react-dom": "^19.0.3",
|
|
8
|
-
"cypress": "13",
|
|
9
8
|
"react-dom": "^19.0.0"
|
|
10
9
|
},
|
|
11
10
|
"devDependencies": {
|
|
12
|
-
"@faststore/core": "^3.
|
|
13
|
-
"@faststore/ui": "^3.
|
|
11
|
+
"@faststore/core": "^3.41.5",
|
|
12
|
+
"@faststore/ui": "^3.41.5",
|
|
14
13
|
"@types/react": "^18.2.42",
|
|
14
|
+
"cypress": "13",
|
|
15
15
|
"next": "13.5.7",
|
|
16
16
|
"typescript": "4.7.3"
|
|
17
17
|
},
|
package/plugin.config.js
CHANGED
|
@@ -5,7 +5,6 @@ module.exports = {
|
|
|
5
5
|
path: "/buyer-portal/[[...contractMode]]",
|
|
6
6
|
appLayout: false,
|
|
7
7
|
},
|
|
8
|
-
|
|
9
8
|
"address-details": {
|
|
10
9
|
path: "/buyer-portal/address/[orgUnitId]/[contractId]/[addressId]",
|
|
11
10
|
appLayout: false,
|
|
@@ -18,7 +17,6 @@ module.exports = {
|
|
|
18
17
|
path: "/buyer-portal/addresses/[orgUnitId]/[contractId]",
|
|
19
18
|
appLayout: false,
|
|
20
19
|
},
|
|
21
|
-
|
|
22
20
|
// Theses Routes will be added in the future
|
|
23
21
|
// "payment-methods": {
|
|
24
22
|
// path: "/buyer-portal/payment-methods/[orgUnitId]/[contractId]",
|
|
@@ -28,10 +26,10 @@ module.exports = {
|
|
|
28
26
|
path: "/buyer-portal/credit-cards/[orgUnitId]/[contractId]",
|
|
29
27
|
appLayout: false,
|
|
30
28
|
},
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
collections: {
|
|
30
|
+
path: "/buyer-portal/collections/[orgUnitId]/[contractId]",
|
|
31
|
+
appLayout: false,
|
|
32
|
+
},
|
|
35
33
|
// "po-numbers": {
|
|
36
34
|
// path: "/buyer-portal/po-numbers/[orgUnitId]/[contractId]",
|
|
37
35
|
// appLayout: false,
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
|
|
1
2
|
<svg style="display:none">
|
|
3
|
+
<symbol
|
|
4
|
+
id="Shapes"
|
|
5
|
+
viewBox="0 0 19 20"
|
|
6
|
+
fill="currentColor"
|
|
7
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
+
>
|
|
9
|
+
<path fill="currentColor" d="M3.5 9L9 0L14.5 9H3.5ZM14.5 20C13.25 20 12.1875 19.5625 11.3125 18.6875C10.4375 17.8125 10 16.75 10 15.5C10 14.25 10.4375 13.1875 11.3125 12.3125C12.1875 11.4375 13.25 11 14.5 11C15.75 11 16.8125 11.4375 17.6875 12.3125C18.5625 13.1875 19 14.25 19 15.5C19 16.75 18.5625 17.8125 17.6875 18.6875C16.8125 19.5625 15.75 20 14.5 20ZM0 19.5V11.5H8V19.5H0ZM14.5 18C15.2 18 15.7917 17.7583 16.275 17.275C16.7583 16.7917 17 16.2 17 15.5C17 14.8 16.7583 14.2083 16.275 13.725C15.7917 13.2417 15.2 13 14.5 13C13.8 13 13.2083 13.2417 12.725 13.725C12.2417 14.2083 12 14.8 12 15.5C12 16.2 12.2417 16.7917 12.725 17.275C13.2083 17.7583 13.8 18 14.5 18ZM2 17.5H6V13.5H2V17.5ZM7.05 7H10.95L9 3.85L7.05 7Z" />
|
|
10
|
+
</symbol>
|
|
11
|
+
|
|
2
12
|
<symbol id="Active" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
|
|
3
13
|
viewBox="0 -960 960 960">
|
|
4
14
|
<path
|
|
@@ -14,6 +24,11 @@
|
|
|
14
24
|
<path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" />
|
|
15
25
|
</symbol>
|
|
16
26
|
|
|
27
|
+
|
|
28
|
+
<symbol id="DoNotDisturb" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
|
29
|
+
<path d="M5 11H15V9H5V11ZM10 20C8.61667 20 7.31667 19.7375 6.1 19.2125C4.88333 18.6875 3.825 17.975 2.925 17.075C2.025 16.175 1.3125 15.1167 0.7875 13.9C0.2625 12.6833 0 11.3833 0 10C0 8.61667 0.2625 7.31667 0.7875 6.1C1.3125 4.88333 2.025 3.825 2.925 2.925C3.825 2.025 4.88333 1.3125 6.1 0.7875C7.31667 0.2625 8.61667 0 10 0C11.3833 0 12.6833 0.2625 13.9 0.7875C15.1167 1.3125 16.175 2.025 17.075 2.925C17.975 3.825 18.6875 4.88333 19.2125 6.1C19.7375 7.31667 20 8.61667 20 10C20 11.3833 19.7375 12.6833 19.2125 13.9C18.6875 15.1167 17.975 16.175 17.075 17.075C16.175 17.975 15.1167 18.6875 13.9 19.2125C12.6833 19.7375 11.3833 20 10 20ZM10 18C12.2333 18 14.125 17.225 15.675 15.675C17.225 14.125 18 12.2333 18 10C18 7.76667 17.225 5.875 15.675 4.325C14.125 2.775 12.2333 2 10 2C7.76667 2 5.875 2.775 4.325 4.325C2.775 5.875 2 7.76667 2 10C2 12.2333 2.775 14.125 4.325 15.675C5.875 17.225 7.76667 18 10 18Z"/>
|
|
30
|
+
</symbol>
|
|
31
|
+
|
|
17
32
|
<symbol
|
|
18
33
|
id="Address" xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"
|
|
19
34
|
fill="currentColor">
|
|
@@ -20,24 +20,37 @@ export default class AddressesClient extends Client {
|
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
getAddressesByUnitId(
|
|
23
|
+
async getAddressesByUnitId(
|
|
24
24
|
orgUnitId: string,
|
|
25
25
|
cookie: string,
|
|
26
26
|
name?: string,
|
|
27
27
|
page = 1
|
|
28
28
|
) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (page && page > 1) params.append("page", String(page));
|
|
32
|
-
const queryString = params.toString();
|
|
29
|
+
let allAddresses: AddressData[] = [];
|
|
30
|
+
let total = 0;
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
for (let currentPage = 1; currentPage <= page; currentPage++) {
|
|
33
|
+
const params = new URLSearchParams();
|
|
34
|
+
if (name) params.append("name", name);
|
|
35
|
+
if (currentPage > 1) params.append("page", String(currentPage));
|
|
36
|
+
const queryString = params.toString();
|
|
37
|
+
const url = queryString
|
|
38
|
+
? `unit/addresses/${orgUnitId}?${queryString}`
|
|
39
|
+
: `unit/addresses/${orgUnitId}`;
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
const response = await this.get<AddressResponse>(url, {
|
|
42
|
+
headers: {
|
|
43
|
+
Cookie: cookie,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (response?.addresses) {
|
|
48
|
+
allAddresses = allAddresses.concat(response.addresses);
|
|
49
|
+
total = response.total;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return { addresses: allAddresses, total };
|
|
41
54
|
}
|
|
42
55
|
|
|
43
56
|
getAddressById(addressId: string, cookie: string) {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Client } from "../../shared/clients/Client";
|
|
2
|
+
import { getApiUrl } from "../../shared/utils";
|
|
3
|
+
import type { RecipientData, RecipientInput } from "../types";
|
|
4
|
+
import type {
|
|
5
|
+
AddRecipientsResponse,
|
|
6
|
+
RecipientsPayload,
|
|
7
|
+
RecipientsResponse,
|
|
8
|
+
} from "../types/AddressData";
|
|
9
|
+
|
|
10
|
+
export default class RecipientsClient extends Client {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(getApiUrl());
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async getRecipientsByCustomerIdAndAddressId(
|
|
16
|
+
customerId: string,
|
|
17
|
+
addressId: string,
|
|
18
|
+
cookie: string,
|
|
19
|
+
name?: string,
|
|
20
|
+
page = 1
|
|
21
|
+
) {
|
|
22
|
+
let recipientsData: RecipientData[] = [];
|
|
23
|
+
let total = 0;
|
|
24
|
+
|
|
25
|
+
for (let currentPage = 1; currentPage <= page; currentPage++) {
|
|
26
|
+
const params = new URLSearchParams();
|
|
27
|
+
if (name) params.append("name", name);
|
|
28
|
+
if (currentPage > 1) params.append("page", String(currentPage));
|
|
29
|
+
const queryString = params.toString();
|
|
30
|
+
|
|
31
|
+
const response = await this.get<RecipientsResponse>(
|
|
32
|
+
`customers/${customerId}/address/${addressId}/recipients?${queryString}`,
|
|
33
|
+
{
|
|
34
|
+
headers: {
|
|
35
|
+
Cookie: cookie,
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (response?.data) {
|
|
41
|
+
recipientsData = recipientsData.concat(response.data);
|
|
42
|
+
total = response.total;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { data: recipientsData, total };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
addRecipientsToAddress(
|
|
50
|
+
customerId: string,
|
|
51
|
+
addressId: string,
|
|
52
|
+
recipients: RecipientInput[],
|
|
53
|
+
cookie: string
|
|
54
|
+
) {
|
|
55
|
+
return this.post<AddRecipientsResponse, RecipientsPayload[]>(
|
|
56
|
+
`customers/${customerId}/address/${addressId}/recipients`,
|
|
57
|
+
recipients.map((recipient) => ({
|
|
58
|
+
name: recipient.recipientName,
|
|
59
|
+
phone: recipient.recipientPhone,
|
|
60
|
+
})),
|
|
61
|
+
{
|
|
62
|
+
headers: {
|
|
63
|
+
Cookie: cookie,
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
editRecipientsToAddress(
|
|
70
|
+
customerId: string,
|
|
71
|
+
addressId: string,
|
|
72
|
+
recipientId: string,
|
|
73
|
+
recipientData: RecipientInput,
|
|
74
|
+
cookie: string
|
|
75
|
+
) {
|
|
76
|
+
return this.put<Response, RecipientsPayload>(
|
|
77
|
+
`customers/${customerId}/address/${addressId}/recipients/${recipientId}`,
|
|
78
|
+
{
|
|
79
|
+
name: recipientData.recipientName,
|
|
80
|
+
phone: recipientData.recipientPhone,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
headers: {
|
|
84
|
+
Cookie: cookie,
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
deleteRecipientFromAddress(
|
|
91
|
+
customerId: string,
|
|
92
|
+
addressId: string,
|
|
93
|
+
recipientId: string,
|
|
94
|
+
cookie: string
|
|
95
|
+
) {
|
|
96
|
+
return this.delete(
|
|
97
|
+
`customers/${customerId}/address/${addressId}/recipients/${recipientId}`,
|
|
98
|
+
null,
|
|
99
|
+
{
|
|
100
|
+
headers: {
|
|
101
|
+
Cookie: cookie,
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const recipientsClient = new RecipientsClient();
|
|
109
|
+
|
|
110
|
+
export { recipientsClient };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { type BasicDrawerProps, BasicDrawer } from "../../../shared/components";
|
|
4
|
+
import { RecipientsForm } from "..";
|
|
5
|
+
import type { RecipientInput } from "../../types";
|
|
6
|
+
import { useUI } from "@faststore/ui";
|
|
7
|
+
import { useAddRecipientsToAddress } from "../../hooks/useAddRecipientsToAddress";
|
|
8
|
+
import { useRouter } from "next/router";
|
|
9
|
+
|
|
10
|
+
export type AddRecipientsDrawerProps = Omit<BasicDrawerProps, "children"> & {
|
|
11
|
+
readonly?: boolean;
|
|
12
|
+
addressId?: string;
|
|
13
|
+
refetchRecipients: () => void;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const AddRecipientsDrawer = ({
|
|
17
|
+
close,
|
|
18
|
+
refetchRecipients,
|
|
19
|
+
addressId,
|
|
20
|
+
readonly,
|
|
21
|
+
...props
|
|
22
|
+
}: AddRecipientsDrawerProps) => {
|
|
23
|
+
const [recipients, setRecipients] = useState<RecipientInput[]>([]);
|
|
24
|
+
const router = useRouter();
|
|
25
|
+
const { pushToast } = useUI();
|
|
26
|
+
|
|
27
|
+
const handleAddRecipientToAddressSuccess = () => {
|
|
28
|
+
pushToast({
|
|
29
|
+
message: "Recipients added successfully ",
|
|
30
|
+
status: "INFO",
|
|
31
|
+
});
|
|
32
|
+
refetchRecipients();
|
|
33
|
+
close();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const { addRecipientsToAddress, isAddRecipientToAddressLoading } =
|
|
37
|
+
useAddRecipientsToAddress({
|
|
38
|
+
onSuccess: handleAddRecipientToAddressSuccess,
|
|
39
|
+
onError: (err) => {
|
|
40
|
+
pushToast({
|
|
41
|
+
message: "An error occurred while adding recipients",
|
|
42
|
+
status: "ERROR",
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const handleConfirmClick = () => {
|
|
48
|
+
if (!isAddRecipientToAddressLoading) {
|
|
49
|
+
addRecipientsToAddress({
|
|
50
|
+
recipients,
|
|
51
|
+
contractId: router.query.contractId as string,
|
|
52
|
+
addressId: addressId ?? (router.query.addressId as string),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const isConfirmButtonEnabled =
|
|
58
|
+
recipients.length > 0 &&
|
|
59
|
+
recipients.every(
|
|
60
|
+
(recipient) =>
|
|
61
|
+
recipient.recipientName.trim() !== "" &&
|
|
62
|
+
recipient.recipientPhone.trim() !== ""
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<BasicDrawer data-fs-bp-create-address-drawer close={close} {...props}>
|
|
67
|
+
<BasicDrawer.Heading title="Add Recipients" onClose={close} />
|
|
68
|
+
<BasicDrawer.Body>
|
|
69
|
+
<RecipientsForm recipients={recipients} setRecipients={setRecipients} />
|
|
70
|
+
</BasicDrawer.Body>
|
|
71
|
+
|
|
72
|
+
<BasicDrawer.Footer>
|
|
73
|
+
<BasicDrawer.Button variant="ghost" onClick={close}>
|
|
74
|
+
Cancel
|
|
75
|
+
</BasicDrawer.Button>
|
|
76
|
+
<BasicDrawer.Button
|
|
77
|
+
variant="confirm"
|
|
78
|
+
isLoading={isAddRecipientToAddressLoading}
|
|
79
|
+
onClick={handleConfirmClick}
|
|
80
|
+
disabled={!isConfirmButtonEnabled}
|
|
81
|
+
>
|
|
82
|
+
Save
|
|
83
|
+
</BasicDrawer.Button>
|
|
84
|
+
</BasicDrawer.Footer>
|
|
85
|
+
</BasicDrawer>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
@@ -3,13 +3,14 @@ import { DropdownItem, Icon as UIIcon } from "@faststore/ui";
|
|
|
3
3
|
import {
|
|
4
4
|
EditAddressDrawer,
|
|
5
5
|
LocationDrawer,
|
|
6
|
-
|
|
6
|
+
AddRecipientsDrawer,
|
|
7
7
|
RemoveAddressDrawer,
|
|
8
8
|
DeleteAddressDrawer,
|
|
9
9
|
} from "..";
|
|
10
10
|
import { useDrawerProps, useBuyerPortal } from "../../../shared/hooks";
|
|
11
11
|
import { BasicDropdownMenu, Icon } from "../../../shared/components";
|
|
12
12
|
import type { AddressData } from "../../types";
|
|
13
|
+
import { useRouter } from "next/router";
|
|
13
14
|
|
|
14
15
|
export type AddressDropdownMenuProps = {
|
|
15
16
|
currentAddress: AddressData;
|
|
@@ -22,10 +23,11 @@ export const AddressDropdownMenu = ({
|
|
|
22
23
|
currentAddress,
|
|
23
24
|
}: AddressDropdownMenuProps) => {
|
|
24
25
|
const { currentOrgUnit } = useBuyerPortal();
|
|
26
|
+
const router = useRouter();
|
|
25
27
|
|
|
26
28
|
const idsPath = currentOrgUnit?.path?.ids?.split("/") ?? [];
|
|
27
29
|
|
|
28
|
-
const isRootLevelOrgUnit = idsPath.length === 2
|
|
30
|
+
const isRootLevelOrgUnit = idsPath.length === 2;
|
|
29
31
|
|
|
30
32
|
const {
|
|
31
33
|
open: openEditDrawerProps,
|
|
@@ -110,10 +112,12 @@ export const AddressDropdownMenu = ({
|
|
|
110
112
|
/>
|
|
111
113
|
)}
|
|
112
114
|
{isOpenRecipientsDrawer && (
|
|
113
|
-
<
|
|
115
|
+
<AddRecipientsDrawer
|
|
114
116
|
readonly
|
|
115
117
|
{...recipientDrawerProps}
|
|
116
118
|
isOpen={isOpenRecipientsDrawer}
|
|
119
|
+
refetchRecipients={() => router.reload()}
|
|
120
|
+
addressId={currentAddress.id}
|
|
117
121
|
/>
|
|
118
122
|
)}
|
|
119
123
|
{isOpenRemoveAddressDrawer && (
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { IconButton } from "@faststore/ui";
|
|
4
|
+
import {
|
|
5
|
+
Icon,
|
|
6
|
+
InternalSearch,
|
|
7
|
+
Paginator,
|
|
8
|
+
Table,
|
|
9
|
+
} from "../../../shared/components";
|
|
10
|
+
import { EmptyState } from "../../../shared/components/EmptyState/EmptyState";
|
|
11
|
+
import { usePageItems } from "../../../shared/hooks/usePageItems";
|
|
12
|
+
import { RecipientData } from "../../types";
|
|
13
|
+
import { maskPhoneNumber } from "../../../shared/utils/phoneNumber";
|
|
14
|
+
import { useDrawerProps } from "../../../shared/hooks";
|
|
15
|
+
import { DeleteRecipientAddressDrawer } from "../DeleteRecipientAddressDrawer/DeleteRecipientAddressDrawer";
|
|
16
|
+
import { EditRecipientAddressDrawer } from "../EditRecipientAddressDrawer/EditRecipientAddressDrawer";
|
|
17
|
+
import { useSearchAddressRecipients } from "../../hooks/useSearchAddressRecipients";
|
|
18
|
+
import { useRouter } from "next/router";
|
|
19
|
+
|
|
20
|
+
export type AddressRecipientsListRef = {
|
|
21
|
+
refetchRecipients: () => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type AddressRecipientsListProps = {
|
|
25
|
+
recipients: RecipientData[];
|
|
26
|
+
total: number;
|
|
27
|
+
search: string;
|
|
28
|
+
page: number;
|
|
29
|
+
countryCode?: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const AddressRecipientsList = forwardRef<
|
|
33
|
+
AddressRecipientsListRef,
|
|
34
|
+
AddressRecipientsListProps
|
|
35
|
+
>(
|
|
36
|
+
(
|
|
37
|
+
{
|
|
38
|
+
recipients: initialRecipients,
|
|
39
|
+
search,
|
|
40
|
+
total,
|
|
41
|
+
page = 1,
|
|
42
|
+
countryCode = "",
|
|
43
|
+
}: AddressRecipientsListProps,
|
|
44
|
+
ref
|
|
45
|
+
) => {
|
|
46
|
+
const router = useRouter();
|
|
47
|
+
|
|
48
|
+
const [totalRecipients, setTotalRecipients] = useState(total);
|
|
49
|
+
|
|
50
|
+
const {
|
|
51
|
+
isLoading,
|
|
52
|
+
items: recipients,
|
|
53
|
+
searchTerm,
|
|
54
|
+
setSearchTerm,
|
|
55
|
+
increasePage,
|
|
56
|
+
setIsLoading,
|
|
57
|
+
setItems,
|
|
58
|
+
} = usePageItems<RecipientData>({
|
|
59
|
+
initialItems: initialRecipients,
|
|
60
|
+
search,
|
|
61
|
+
page,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const [currentRecipient, setCurrentRecipient] = useState<RecipientData>();
|
|
65
|
+
|
|
66
|
+
const { searchAddressRecipients, refetchSearchAddressRecipients } =
|
|
67
|
+
useSearchAddressRecipients({
|
|
68
|
+
addressId: router.query.addressId as string,
|
|
69
|
+
contractId: router.query.contractId as string,
|
|
70
|
+
page: 1,
|
|
71
|
+
search: search ?? "",
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (searchAddressRecipients?.data) {
|
|
76
|
+
setItems(searchAddressRecipients.data);
|
|
77
|
+
setTotalRecipients(searchAddressRecipients.total);
|
|
78
|
+
setIsLoading(false);
|
|
79
|
+
}
|
|
80
|
+
}, [searchAddressRecipients]);
|
|
81
|
+
|
|
82
|
+
const handleRefetchRecipients = () => {
|
|
83
|
+
setIsLoading(true);
|
|
84
|
+
refetchSearchAddressRecipients();
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
useImperativeHandle(ref, () => ({
|
|
88
|
+
refetchRecipients: handleRefetchRecipients,
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
const {
|
|
92
|
+
open: openDeleteRecipientsAddressDrawer,
|
|
93
|
+
isOpen: isOpenDeleteRecipientAddressDrawer,
|
|
94
|
+
...deleteRecipientAddressDrawerProps
|
|
95
|
+
} = useDrawerProps();
|
|
96
|
+
|
|
97
|
+
const {
|
|
98
|
+
open: openEditRecipientsAddressDrawer,
|
|
99
|
+
isOpen: isOpenEditRecipientAddressDrawer,
|
|
100
|
+
...editRecipientAddressDrawerProps
|
|
101
|
+
} = useDrawerProps();
|
|
102
|
+
|
|
103
|
+
const renderActions = (recipient: RecipientData) => {
|
|
104
|
+
return (
|
|
105
|
+
<div data-fs-buyer-portal-recipients-actions>
|
|
106
|
+
<IconButton
|
|
107
|
+
data-fs-buyer-portal-recipients-actions-icon
|
|
108
|
+
icon={<Icon name="Trash" width={20} height={20} />}
|
|
109
|
+
aria-label={"remove recipient action"}
|
|
110
|
+
onClick={() => {
|
|
111
|
+
setCurrentRecipient(recipient);
|
|
112
|
+
openDeleteRecipientsAddressDrawer();
|
|
113
|
+
}}
|
|
114
|
+
/>
|
|
115
|
+
<IconButton
|
|
116
|
+
data-fs-buyer-portal-recipients-actions-icon
|
|
117
|
+
icon={<Icon name="Edit" width={20} height={20} />}
|
|
118
|
+
aria-label={"Edit recipient action"}
|
|
119
|
+
onClick={() => {
|
|
120
|
+
setCurrentRecipient(recipient);
|
|
121
|
+
openEditRecipientsAddressDrawer();
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div data-fs-buyer-portal-address-recipients-list>
|
|
130
|
+
<div data-fs-buyer-portal-address-recipients-filter>
|
|
131
|
+
<InternalSearch
|
|
132
|
+
defaultValue={searchTerm}
|
|
133
|
+
textSearch={setSearchTerm}
|
|
134
|
+
/>
|
|
135
|
+
|
|
136
|
+
<Paginator.Counter
|
|
137
|
+
total={totalRecipients}
|
|
138
|
+
itemsLength={recipients.length}
|
|
139
|
+
/>
|
|
140
|
+
</div>
|
|
141
|
+
{!isLoading && recipients.length === 0 && searchTerm.length > 0 ? (
|
|
142
|
+
<EmptyState
|
|
143
|
+
title="No results found"
|
|
144
|
+
description="Try using different terms or filters"
|
|
145
|
+
/>
|
|
146
|
+
) : (
|
|
147
|
+
<div data-fs-address-recipients-table>
|
|
148
|
+
<Table>
|
|
149
|
+
<Table.Head
|
|
150
|
+
columns={[
|
|
151
|
+
{
|
|
152
|
+
key: "name",
|
|
153
|
+
label: "Name",
|
|
154
|
+
align: "left",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
key: "phone",
|
|
158
|
+
label: "Phone",
|
|
159
|
+
align: "left",
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
key: "actions",
|
|
163
|
+
label: "",
|
|
164
|
+
align: "right",
|
|
165
|
+
size: "large",
|
|
166
|
+
},
|
|
167
|
+
]}
|
|
168
|
+
/>
|
|
169
|
+
|
|
170
|
+
<Table.Body>
|
|
171
|
+
{isLoading ? (
|
|
172
|
+
<Table.Loading />
|
|
173
|
+
) : (
|
|
174
|
+
recipients.map((recipient) => (
|
|
175
|
+
<Table.Row
|
|
176
|
+
key={recipient.id}
|
|
177
|
+
title={recipient.firstName + " " + recipient.lastName}
|
|
178
|
+
searchTerm={search}
|
|
179
|
+
children={
|
|
180
|
+
recipient.phone ? (
|
|
181
|
+
<td>
|
|
182
|
+
<span>
|
|
183
|
+
{maskPhoneNumber(recipient.phone, countryCode)}
|
|
184
|
+
</span>
|
|
185
|
+
</td>
|
|
186
|
+
) : null
|
|
187
|
+
}
|
|
188
|
+
actionIcons={renderActions(recipient as RecipientData)}
|
|
189
|
+
/>
|
|
190
|
+
))
|
|
191
|
+
)}
|
|
192
|
+
</Table.Body>
|
|
193
|
+
</Table>
|
|
194
|
+
|
|
195
|
+
{isOpenDeleteRecipientAddressDrawer && currentRecipient && (
|
|
196
|
+
<DeleteRecipientAddressDrawer
|
|
197
|
+
readonly
|
|
198
|
+
recipientAddressName={
|
|
199
|
+
currentRecipient.firstName + " " + currentRecipient.lastName
|
|
200
|
+
}
|
|
201
|
+
recipientAddressId={currentRecipient.id}
|
|
202
|
+
isOpen={isOpenDeleteRecipientAddressDrawer}
|
|
203
|
+
refetchRecipients={handleRefetchRecipients}
|
|
204
|
+
{...deleteRecipientAddressDrawerProps}
|
|
205
|
+
/>
|
|
206
|
+
)}
|
|
207
|
+
|
|
208
|
+
{isOpenEditRecipientAddressDrawer && currentRecipient && (
|
|
209
|
+
<EditRecipientAddressDrawer
|
|
210
|
+
readonly
|
|
211
|
+
recipient={currentRecipient}
|
|
212
|
+
isOpen={isOpenEditRecipientAddressDrawer}
|
|
213
|
+
refetchRecipients={handleRefetchRecipients}
|
|
214
|
+
{...editRecipientAddressDrawerProps}
|
|
215
|
+
/>
|
|
216
|
+
)}
|
|
217
|
+
|
|
218
|
+
<div data-fs-bp-address-recipients-paginator>
|
|
219
|
+
{totalRecipients > recipients.length && (
|
|
220
|
+
<Paginator.NextPageButton
|
|
221
|
+
onClick={increasePage}
|
|
222
|
+
disabled={isLoading}
|
|
223
|
+
>
|
|
224
|
+
{isLoading ? "Loading" : "Load More"}
|
|
225
|
+
</Paginator.NextPageButton>
|
|
226
|
+
)}
|
|
227
|
+
|
|
228
|
+
<Paginator.Counter
|
|
229
|
+
total={totalRecipients}
|
|
230
|
+
itemsLength={recipients.length}
|
|
231
|
+
/>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
)}
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
);
|