@vtex/faststore-plugin-buyer-portal 1.0.25 → 1.0.26
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/package.json +6 -3
- package/plugin.config.js +8 -4
- package/public/buyer-portal-icons.svg +24 -0
- package/src/clients/BuyerPortalClient.ts +128 -0
- package/src/clients/Client.ts +95 -0
- package/src/components/AddressLine/address-line.scss +5 -5
- package/src/components/AddressesCard/AddressesCard.tsx +4 -4
- package/src/components/AutocompleteDropdown/AutocompleteDropdown.tsx +175 -0
- package/src/components/AutocompleteDropdown/AutocompleteDropdownItem.tsx +39 -0
- package/src/components/AutocompleteDropdown/autocomplete-dropdown.scss +45 -0
- package/src/components/AutocompleteDropdown/useAutocompletePosition.ts +86 -0
- package/src/components/{HomeCard/HomeCard.tsx → BasicCard/BasicCard.tsx} +7 -5
- package/src/components/BasicDrawer/BasicDrawer.tsx +37 -0
- package/src/components/BasicDrawer/BasicDrawerBody.tsx +16 -0
- package/src/components/BasicDrawer/BasicDrawerButton.tsx +34 -0
- package/src/components/BasicDrawer/BasicDrawerFooter.tsx +16 -0
- package/src/components/BasicDrawer/BasicDrawerHeading.tsx +27 -0
- package/src/components/BasicDrawer/basic-drawer.scss +121 -0
- package/src/components/BasicDropdownMenu/BasicDropdownMenu.tsx +13 -0
- package/src/components/BasicDropdownMenu/basic-dropdown-menu.scss +19 -0
- package/src/components/Card/card.scss +59 -36
- package/src/components/ContractsCard/ContractsCard.tsx +19 -119
- package/src/components/CreateOrgUnitDrawer/CreateOrgUnitDrawer.tsx +126 -4
- package/src/components/CreateOrgUnitDrawer/create-org-unit-drawer.scss +6 -0
- package/src/components/CustomerSwitch/CustomerSwitchDrawer.tsx +0 -1
- package/src/components/CustomerSwitch/customer-switch.scss +9 -9
- package/src/components/DeleteOrgUnitDrawer/DeleteOrgUnitDrawer.tsx +145 -0
- package/src/components/DeleteOrgUnitDrawer/delete-org-unit-drawer.scss +81 -0
- package/src/components/DropdownFilter/dropdown-filter.scss +2 -2
- package/src/components/ErrorMessage/ErrorMessage.tsx +7 -0
- package/src/components/ErrorMessage/error-message.scss +7 -0
- package/src/components/HierarchyTree/HierarchyTree.tsx +3 -3
- package/src/components/InputText/InputText.tsx +82 -0
- package/src/components/InputText/input-text.scss +93 -0
- package/src/components/InternalSearch/internal-search.scss +2 -2
- package/src/components/InternalTopbar/InternalTopbar.tsx +1 -1
- package/src/components/InternalTopbar/internal-top-bar.scss +13 -24
- package/src/components/MainLinksDropdownMenu/MainLinksDropdownMenu.tsx +2 -2
- package/src/components/Navbar/navbar.scss +1 -1
- package/src/components/OrgUnitsDropdownMenu/OrgUnitsDropdownMenu.tsx +80 -0
- package/src/components/OrgUnitsDropdownMenu/org-units-dropdown-menu.scss +4 -0
- package/src/components/OrgUnitsHierarchyTree/OrgUnitsHierarchyTree.tsx +66 -25
- package/src/components/OrgUnitsHierarchyTree/org-units-hierarchy-tree.scss +56 -25
- package/src/components/OrganizationalUnitsCard/OrganizationalUnitsCard.tsx +44 -77
- package/src/components/ProfileCard/ProfileCard.tsx +3 -3
- package/src/components/ProfileSummary/profile-summary.scss +7 -7
- package/src/components/SelfManagementDrawer/self-management-drawer.scss +23 -21
- package/src/components/SortFilter/sort-filter.scss +2 -2
- package/src/components/Tab/Tab.tsx +40 -0
- package/src/components/Tab/TabBar.tsx +7 -0
- package/src/components/Tab/TabContent.tsx +14 -0
- package/src/components/Tab/TabOption.tsx +20 -0
- package/src/components/Tab/tab.scss +19 -0
- package/src/components/Toast/Toast.tsx +53 -0
- package/src/components/Toast/toast.scss +124 -0
- package/src/components/UpdateOrgUnitDrawer/UpdateOrgUnitDrawer.tsx +123 -0
- package/src/components/UpdateOrgUnitDrawer/update-org-unit-drawer.scss +6 -0
- package/src/components/UsersCard/UsersCard.tsx +15 -19
- package/src/hooks/useChildrenOrgUnits.ts +19 -0
- package/src/hooks/useCreateNewOrgUnit.ts +28 -0
- package/src/hooks/useDeleteOrgUnit.ts +24 -0
- package/src/hooks/useDrawerProps.ts +32 -0
- package/src/hooks/useMutation.ts +51 -0
- package/src/hooks/useOrgUnitStructure.ts +63 -0
- package/src/hooks/useQuery.ts +49 -0
- package/src/hooks/useRootOrgUnitByCustomer.ts +19 -0
- package/src/hooks/useUpdateOrgUnit.ts +24 -0
- package/src/hooks/useUsersByOrgUnit.ts +20 -0
- package/src/layouts/AddressDetailsLayout/address-details-layout.scss +9 -9
- package/src/layouts/AddressesLayout/addresses-layout.scss +3 -2
- package/src/layouts/ContractsLayout/ContractsLayout.tsx +1 -1
- package/src/layouts/ContractsLayout/contracts-layout.scss +1 -1
- package/src/layouts/GlobalLayout/GlobalLayout.tsx +4 -0
- package/src/layouts/GlobalLayout/global-layout.scss +1 -0
- package/src/layouts/HomeLayout/HomeLayout.tsx +22 -22
- package/src/layouts/HomeLayout/home-layout.scss +10 -8
- package/src/layouts/OrgUnitDetailsLayout/OrgUnitDetailsLayout.tsx +34 -0
- package/src/layouts/OrgUnitsLayout/OrgUnitsLayout.tsx +27 -9
- package/src/layouts/OrgUnitsLayout/org-units-layout.scss +9 -4
- package/src/layouts/ProfileLayout/profile-layout.scss +7 -7
- package/src/layouts/UserDetailsLayout/UserDetailsLayout.tsx +1 -1
- package/src/layouts/UserDetailsLayout/user-details-layout.scss +16 -15
- package/src/layouts/UsersLayout/UsersLayout.tsx +16 -12
- package/src/layouts/UsersLayout/users-layout.scss +20 -20
- package/src/mock/contracts-data.ts +3 -3
- package/src/mock/org-units-data.ts +31 -31
- package/src/mock/organization-data.ts +8 -1
- package/src/mock/users-data.ts +10 -4
- package/src/pages/address-details.tsx +18 -5
- package/src/pages/addresses.tsx +11 -3
- package/src/pages/contracts.tsx +24 -12
- package/src/pages/home.tsx +14 -3
- package/src/pages/org-unit-details.tsx +41 -0
- package/src/pages/org-units.tsx +23 -10
- package/src/pages/profile.tsx +14 -4
- package/src/pages/user-details.tsx +13 -7
- package/src/pages/users.tsx +23 -9
- package/src/services/create-new-org-unit.service.ts +15 -0
- package/src/services/delete-org-unit.service.ts +13 -0
- package/src/services/get-addresses.service.ts +33 -47
- package/src/services/get-children-org-units.service.ts +18 -0
- package/src/services/get-contracts.service.ts +22 -41
- package/src/services/get-org-unit-by-id.service.ts +25 -0
- package/src/services/get-org-unit-summary.service.ts +13 -0
- package/src/services/get-organization.service.ts +10 -7
- package/src/services/get-root-org-unit-by-customer-id.service.ts +10 -0
- package/src/services/get-users-by-org-unit-id.service.ts +9 -0
- package/src/services/get-users.service.ts +7 -19
- package/src/services/update-org-unit.service.ts +14 -0
- package/src/themes/index.scss +13 -12
- package/src/types/AwaitedType.d.ts +1 -0
- package/src/types/BreadcrumbData.ts +6 -0
- package/src/types/ContractData.ts +5 -2
- package/src/types/OrgUnitSummaryData.ts +10 -0
- package/src/types/OrgUnitsData.ts +3 -1
- package/src/types/OrganizationData.ts +3 -2
- package/src/types/UserData.ts +5 -2
- package/src/utils/api.ts +6 -4
- package/src/utils/compareItems.ts +19 -0
- package/src/utils/constants.ts +5 -4
- package/src/utils/cookie.ts +1 -1
- package/src/utils/getClientContext.ts +9 -1
- package/src/utils/getTreeDepth.ts +3 -6
- package/src/utils/search.tsx +2 -2
- package/src/utils/toQueryParams.ts +14 -0
- package/src/services/get-org-units-hierarchy.service.ts +0 -7
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vtex/faststore-plugin-buyer-portal",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"description": "A plugin for faststore with buyer portal",
|
|
5
5
|
"main": "index.js",
|
|
6
|
-
"dependencies": {
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@types/react-dom": "^19.0.3",
|
|
8
|
+
"react-dom": "^19.0.0"
|
|
9
|
+
},
|
|
7
10
|
"devDependencies": {
|
|
8
11
|
"@faststore/core": "^3.0.147",
|
|
9
12
|
"@faststore/ui": "^3.0.147",
|
|
10
13
|
"@types/react": "^18.2.42",
|
|
11
|
-
"next": "13.5.
|
|
14
|
+
"next": "13.5.7",
|
|
12
15
|
"typescript": "4.7.3"
|
|
13
16
|
},
|
|
14
17
|
"peerDependencies": {
|
package/plugin.config.js
CHANGED
|
@@ -5,12 +5,16 @@ module.exports = {
|
|
|
5
5
|
path: "/buyer-portal/[[...contractMode]]",
|
|
6
6
|
appLayout: false,
|
|
7
7
|
},
|
|
8
|
+
"org-unit-details": {
|
|
9
|
+
path: "/org-unit/[orgUnitId]",
|
|
10
|
+
appLayout: false,
|
|
11
|
+
},
|
|
8
12
|
"org-units": {
|
|
9
|
-
path: "/org-units",
|
|
13
|
+
path: "/org-units/[[...orgUnitId]]",
|
|
10
14
|
appLayout: false,
|
|
11
15
|
},
|
|
12
16
|
contracts: {
|
|
13
|
-
path: "/contracts",
|
|
17
|
+
path: "/contracts/[[...orgUnitId]]",
|
|
14
18
|
appLayout: false,
|
|
15
19
|
},
|
|
16
20
|
addresses: {
|
|
@@ -18,7 +22,7 @@ module.exports = {
|
|
|
18
22
|
appLayout: false,
|
|
19
23
|
},
|
|
20
24
|
"address-details": {
|
|
21
|
-
path: "/address/[
|
|
25
|
+
path: "/address/[addressId]",
|
|
22
26
|
appLayout: false,
|
|
23
27
|
},
|
|
24
28
|
users: {
|
|
@@ -26,7 +30,7 @@ module.exports = {
|
|
|
26
30
|
appLayout: false,
|
|
27
31
|
},
|
|
28
32
|
"user-details": {
|
|
29
|
-
path: "/user/[
|
|
33
|
+
path: "/user/[userId]",
|
|
30
34
|
appLayout: false,
|
|
31
35
|
},
|
|
32
36
|
profile: {
|
|
@@ -62,6 +62,13 @@
|
|
|
62
62
|
stroke-linejoin="round"></polyline>
|
|
63
63
|
</symbol>
|
|
64
64
|
|
|
65
|
+
<symbol id="Check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 10"
|
|
66
|
+
fill="currentColor">
|
|
67
|
+
<path
|
|
68
|
+
d="M4.10417 9.4375L0.0625 5.41667L1.125 4.33333L4.10417 7.3125L10.875 0.5625L11.9375 1.625L4.10417 9.4375Z"
|
|
69
|
+
fill="currentColor" />
|
|
70
|
+
</symbol>
|
|
71
|
+
|
|
65
72
|
|
|
66
73
|
<symbol
|
|
67
74
|
id="Delete" xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"
|
|
@@ -183,6 +190,16 @@
|
|
|
183
190
|
d="M480-160q-33 0-56.5-23.5T400-240q0-33 23.5-56.5T480-320q33 0 56.5 23.5T560-240q0 33-23.5 56.5T480-160Zm0-240q-33 0-56.5-23.5T400-480q0-33 23.5-56.5T480-560q33 0 56.5 23.5T560-480q0 33-23.5 56.5T480-400Zm0-240q-33 0-56.5-23.5T400-720q0-33 23.5-56.5T480-800q33 0 56.5 23.5T560-720q0 33-23.5 56.5T480-640Z" />
|
|
184
191
|
</symbol>
|
|
185
192
|
|
|
193
|
+
<symbol
|
|
194
|
+
id="Close"
|
|
195
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
196
|
+
viewBox="0 0 14 14"
|
|
197
|
+
fill="none">
|
|
198
|
+
<path
|
|
199
|
+
d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z"
|
|
200
|
+
fill="currentColor" />
|
|
201
|
+
</symbol>
|
|
202
|
+
|
|
186
203
|
|
|
187
204
|
<symbol
|
|
188
205
|
id="OpenInNew"
|
|
@@ -216,4 +233,11 @@
|
|
|
216
233
|
<path
|
|
217
234
|
d="M154-128q-43.72 0-74.86-31.14Q48-190.27 48-234v-492q0-43.72 31.14-74.86T154-832h220l106 106h326q43.72 0 74.86 31.14T912-620v386q0 43.73-31.14 74.86Q849.72-128 806-128H154Zm339.67-136 104.16-79.68L702-264l-38-130 104-84H638l-40-126-40 126H428l104.17 84.23L493.67-264Z" />
|
|
218
235
|
</symbol>
|
|
236
|
+
|
|
237
|
+
<symbol id="LoadingIndicator" xmlns="http://www.w3.org/2000/svg"
|
|
238
|
+
viewBox="0 0 18 18" fill="none">
|
|
239
|
+
<path
|
|
240
|
+
d="M17.4643 5.99996L15.5245 6.51972C16.2578 8.40957 16.1575 10.6033 15.0625 12.4999C13.1275 15.8514 8.85184 16.9971 5.50032 15.0621C2.1488 13.1271 1.00314 8.85143 2.93814 5.49992C4.03314 3.60332 5.88283 2.41957 7.88249 2.09606L7.36639 0.169961C4.8613 0.628903 2.57609 2.12701 1.20609 4.49992C-1.27891 8.80406 0.196175 14.3091 4.50032 16.7941C8.80447 19.2791 14.3096 17.8041 16.7946 13.4999C18.1646 11.127 18.3193 8.3989 17.4643 5.99996Z"
|
|
241
|
+
fill="currentColor" />
|
|
242
|
+
</symbol>
|
|
219
243
|
</svg>
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { AddressData } from "../types/AddressData";
|
|
2
|
+
import type { ContractData } from "../types/ContractData";
|
|
3
|
+
import type { OrgUnitData } from "../types/OrgUnitsData";
|
|
4
|
+
import type { OrgUnitSummaryData } from "../types/OrgUnitSummaryData";
|
|
5
|
+
import { getApiUrl } from "../utils/api";
|
|
6
|
+
import Client from "./Client";
|
|
7
|
+
|
|
8
|
+
class BuyerPortalClient extends Client {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(getApiUrl());
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Contracts
|
|
14
|
+
getContractsByCustomerId(customerId: string, cookie: string) {
|
|
15
|
+
return this.get<{ data: { contracts: ContractData[]; total: number } }>(
|
|
16
|
+
`contracts/${customerId}`,
|
|
17
|
+
{
|
|
18
|
+
headers: {
|
|
19
|
+
Cookie: cookie,
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getContracts(
|
|
26
|
+
cookie: string,
|
|
27
|
+
params?: {
|
|
28
|
+
salesRepresentative?: string;
|
|
29
|
+
isActive?: boolean;
|
|
30
|
+
page?: number;
|
|
31
|
+
sort?: "Asc" | "Desc";
|
|
32
|
+
}
|
|
33
|
+
) {
|
|
34
|
+
return this.get<ContractData[]>("contracts/filter", {
|
|
35
|
+
headers: {
|
|
36
|
+
Cookie: cookie,
|
|
37
|
+
},
|
|
38
|
+
params,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//Addresses
|
|
43
|
+
getAddressesByCustomerId(customerId: string, cookie: string) {
|
|
44
|
+
return this.get<{ addresses: AddressData[] }>(`addresses/${customerId}`, {
|
|
45
|
+
headers: {
|
|
46
|
+
Cookie: cookie,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Users
|
|
52
|
+
// getUsersByOrgUnitId(orgUnitId: string, cookie: string) {
|
|
53
|
+
// return this.get<ContractData[]>(`getUsers/${orgUnitId}`, {
|
|
54
|
+
// headers: {
|
|
55
|
+
// Cookie: cookie,
|
|
56
|
+
// },
|
|
57
|
+
// });
|
|
58
|
+
// }
|
|
59
|
+
|
|
60
|
+
//Org Units
|
|
61
|
+
getOrgUnitSummary(id: string, cookie: string) {
|
|
62
|
+
return this.get<OrgUnitSummaryData>(`units/summary/${id}`, {
|
|
63
|
+
headers: {
|
|
64
|
+
Cookie: cookie,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getRootOrgUnitByCustomerId(customerId: string, cookie: string) {
|
|
70
|
+
return this.get<{ organizationalUnits: OrgUnitData[]; total: number }>(
|
|
71
|
+
`units/root/${customerId}`,
|
|
72
|
+
{
|
|
73
|
+
headers: {
|
|
74
|
+
Cookie: cookie,
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
createOrgUnit(
|
|
81
|
+
{
|
|
82
|
+
parentId,
|
|
83
|
+
...data
|
|
84
|
+
}: { name: string; parentId: string | null; customerId: string[] },
|
|
85
|
+
cookie: string
|
|
86
|
+
) {
|
|
87
|
+
return this.post(
|
|
88
|
+
"units",
|
|
89
|
+
{ ...data, ...(parentId && { parentId }) },
|
|
90
|
+
{
|
|
91
|
+
headers: {
|
|
92
|
+
Cookie: cookie,
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
updateOrgUnit(
|
|
99
|
+
{ id, ...data }: { name?: string; id: string },
|
|
100
|
+
cookie: string
|
|
101
|
+
) {
|
|
102
|
+
return this.patch(`units/${id}`, data, {
|
|
103
|
+
headers: {
|
|
104
|
+
Cookie: cookie,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
deleteOrgUnit(orgUnitId: string, cookie: string) {
|
|
110
|
+
return this.delete(`units/${orgUnitId}`, {
|
|
111
|
+
headers: {
|
|
112
|
+
Cookie: cookie,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// getChildrenByOrgUnitId(orgUnitId: string, cookie: string) {
|
|
118
|
+
// return this.get<ContractData[]>(`getChildren/${orgUnitId}`, {
|
|
119
|
+
// headers: {
|
|
120
|
+
// Cookie: cookie,
|
|
121
|
+
// },
|
|
122
|
+
// });
|
|
123
|
+
// }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const buyerPortalClient = new BuyerPortalClient();
|
|
127
|
+
|
|
128
|
+
export { buyerPortalClient };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { toQueryParams } from "../utils/toQueryParams";
|
|
2
|
+
|
|
3
|
+
interface RequestConfig<T> {
|
|
4
|
+
url: string;
|
|
5
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
6
|
+
data?: T;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
params?: Record<string, string | number | boolean>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class Client {
|
|
12
|
+
private baseURL: string;
|
|
13
|
+
|
|
14
|
+
constructor(baseURL = "") {
|
|
15
|
+
this.baseURL = baseURL;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async request<T>({
|
|
19
|
+
url,
|
|
20
|
+
method,
|
|
21
|
+
data,
|
|
22
|
+
headers = {},
|
|
23
|
+
params = {},
|
|
24
|
+
}: RequestConfig<T>): Promise<T> {
|
|
25
|
+
const config: RequestInit = {
|
|
26
|
+
method,
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
...headers,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const paramsString = toQueryParams(params);
|
|
34
|
+
|
|
35
|
+
if (data) {
|
|
36
|
+
config.body = JSON.stringify(data);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const response = await fetch(this.baseURL + url + paramsString, config);
|
|
41
|
+
let responseData: T | null = null;
|
|
42
|
+
|
|
43
|
+
const contentType = response.headers.get("Content-Type");
|
|
44
|
+
if (contentType?.includes("application/json")) {
|
|
45
|
+
responseData = await response.json();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
responseData
|
|
51
|
+
? (responseData as unknown as { message: string }).message
|
|
52
|
+
: "Request failed"
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return responseData as T;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return Promise.reject(error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get<T>(url: string, config: Partial<RequestConfig<T>> = {}): Promise<T> {
|
|
63
|
+
return this.request<T>({ url, method: "GET", ...config });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
post<T>(
|
|
67
|
+
url: string,
|
|
68
|
+
data: T,
|
|
69
|
+
config: Partial<RequestConfig<T>> = {}
|
|
70
|
+
): Promise<T> {
|
|
71
|
+
return this.request<T>({ url, method: "POST", data, ...config });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
put<T>(
|
|
75
|
+
url: string,
|
|
76
|
+
data: T,
|
|
77
|
+
config: Partial<RequestConfig<T>> = {}
|
|
78
|
+
): Promise<T> {
|
|
79
|
+
return this.request<T>({ url, method: "PUT", data, ...config });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
patch<T>(
|
|
83
|
+
url: string,
|
|
84
|
+
data: T,
|
|
85
|
+
config: Partial<RequestConfig<T>> = {}
|
|
86
|
+
): Promise<T> {
|
|
87
|
+
return this.request<T>({ url, method: "PATCH", data, ...config });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
delete<T>(url: string, config: Partial<RequestConfig<T>> = {}): Promise<T> {
|
|
91
|
+
return this.request<T>({ url, method: "DELETE", ...config });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export default Client;
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
|
|
28
28
|
[data-fs-addresses-line-icon] {
|
|
29
29
|
color: #0068d7;
|
|
30
|
-
margin:
|
|
31
|
-
margin-right:
|
|
30
|
+
margin: calc(var(--fs-spacing-2) - var(--fs-spacing-0));
|
|
31
|
+
margin-right: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
[data-fs-addresses-line-name] {
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
|
|
53
53
|
[data-fs-addresses-dropdown-trigger] {
|
|
54
54
|
cursor: pointer;
|
|
55
|
-
height:
|
|
56
|
-
width:
|
|
57
|
-
border-radius:
|
|
55
|
+
height: var(--fs-spacing-6);
|
|
56
|
+
width: var(--fs-spacing-6);
|
|
57
|
+
border-radius: var(--fs-border-radius-pill);
|
|
58
58
|
&:hover {
|
|
59
59
|
background-color: #e0e0e0;
|
|
60
60
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { Tag } from "../Tag/Tag";
|
|
9
9
|
import { AddressData } from "../../types/AddressData";
|
|
10
10
|
import { Icon } from "../Icon";
|
|
11
|
-
import {
|
|
11
|
+
import { BasicCard } from "../BasicCard/BasicCard";
|
|
12
12
|
|
|
13
13
|
type AddressesCardProps = {
|
|
14
14
|
addresses: AddressData[];
|
|
@@ -16,7 +16,7 @@ type AddressesCardProps = {
|
|
|
16
16
|
|
|
17
17
|
export default function AddressesCard({ addresses }: AddressesCardProps) {
|
|
18
18
|
return (
|
|
19
|
-
<
|
|
19
|
+
<BasicCard
|
|
20
20
|
footerLink="/addresses"
|
|
21
21
|
footerMessage="Manage addresses"
|
|
22
22
|
title="Addresses"
|
|
@@ -74,7 +74,7 @@ export default function AddressesCard({ addresses }: AddressesCardProps) {
|
|
|
74
74
|
/>{" "}
|
|
75
75
|
Delete
|
|
76
76
|
</DropdownItem>
|
|
77
|
-
<DropdownItem>
|
|
77
|
+
<DropdownItem dismissOnClick={false}>
|
|
78
78
|
<div data-fs-dropdown-active-item>
|
|
79
79
|
<div data-fs-dropdown-active-item-label>
|
|
80
80
|
<Icon
|
|
@@ -99,6 +99,6 @@ export default function AddressesCard({ addresses }: AddressesCardProps) {
|
|
|
99
99
|
</div>
|
|
100
100
|
);
|
|
101
101
|
})}
|
|
102
|
-
</
|
|
102
|
+
</BasicCard>
|
|
103
103
|
);
|
|
104
104
|
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { InputText } from "../InputText/InputText";
|
|
2
|
+
import {
|
|
3
|
+
useRef,
|
|
4
|
+
useState,
|
|
5
|
+
KeyboardEvent,
|
|
6
|
+
ComponentProps,
|
|
7
|
+
useEffect,
|
|
8
|
+
ReactNode,
|
|
9
|
+
createContext,
|
|
10
|
+
useContext,
|
|
11
|
+
} from "react";
|
|
12
|
+
import { createPortal } from "react-dom";
|
|
13
|
+
import { useAutocompletePosition } from "./useAutocompletePosition";
|
|
14
|
+
import { Icon } from "../Icon";
|
|
15
|
+
import { AutocompleteDropdownItem } from "./AutocompleteDropdownItem";
|
|
16
|
+
|
|
17
|
+
export type AutocompleteDropdownContextProps = {
|
|
18
|
+
focusedItemIndex: number;
|
|
19
|
+
setFocusedItemIndex: (index: number) => void;
|
|
20
|
+
close: () => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const AutocompleteDropdownContext =
|
|
24
|
+
createContext<AutocompleteDropdownContextProps | null>(null);
|
|
25
|
+
|
|
26
|
+
export const useAutocompleteDropdownContext = () => {
|
|
27
|
+
const context = useContext(AutocompleteDropdownContext);
|
|
28
|
+
|
|
29
|
+
if (!context) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
"AutocompleteDropdown compound components cannot be rendered outside the AutocompleteDropdown component"
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return context;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type AutocompleteDropdownProps<T> = ComponentProps<"input"> & {
|
|
39
|
+
label: string;
|
|
40
|
+
options?: T[];
|
|
41
|
+
renderOption?: (option: T, index: number) => ReactNode;
|
|
42
|
+
onConfirmKeyPress?: (option: T) => void;
|
|
43
|
+
hasError?: boolean;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const AutocompleteDropdown = <T,>({
|
|
47
|
+
label,
|
|
48
|
+
options = [],
|
|
49
|
+
onChange,
|
|
50
|
+
renderOption,
|
|
51
|
+
onInput,
|
|
52
|
+
disabled,
|
|
53
|
+
onConfirmKeyPress,
|
|
54
|
+
hasError,
|
|
55
|
+
...props
|
|
56
|
+
}: AutocompleteDropdownProps<T>) => {
|
|
57
|
+
const [isOpened, setIsOpened] = useState(false);
|
|
58
|
+
|
|
59
|
+
const [focusedItemIndex, setFocusedItemIndex] = useState(0);
|
|
60
|
+
|
|
61
|
+
const autocompleteMenuRef = useRef<HTMLDivElement>(null);
|
|
62
|
+
const wrapperAutocompleteRef = useRef<HTMLDivElement>(null);
|
|
63
|
+
|
|
64
|
+
const positionStyle = useAutocompletePosition(
|
|
65
|
+
"left",
|
|
66
|
+
isOpened,
|
|
67
|
+
wrapperAutocompleteRef
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const handleClick = () => {
|
|
71
|
+
!disabled && setIsOpened((old) => !old);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const handleBackdropKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
|
|
75
|
+
if (event.defaultPrevented || event.key === " ") {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
|
|
81
|
+
switch (event.key) {
|
|
82
|
+
case "Enter":
|
|
83
|
+
onConfirmKeyPress?.(options[focusedItemIndex]);
|
|
84
|
+
break;
|
|
85
|
+
case "ArrowDown":
|
|
86
|
+
focusedItemIndex < options.length - 1 &&
|
|
87
|
+
setFocusedItemIndex(focusedItemIndex + 1);
|
|
88
|
+
break;
|
|
89
|
+
case "ArrowUp":
|
|
90
|
+
focusedItemIndex > 0 && setFocusedItemIndex(focusedItemIndex - 1);
|
|
91
|
+
break;
|
|
92
|
+
case "Home":
|
|
93
|
+
setFocusedItemIndex(0);
|
|
94
|
+
break;
|
|
95
|
+
case "End":
|
|
96
|
+
setFocusedItemIndex(options.length - 1);
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const close = () => {
|
|
104
|
+
setIsOpened(false);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
const event = (e: MouseEvent) => {
|
|
109
|
+
const target = e.target as Node;
|
|
110
|
+
const wasSomeItemClicked =
|
|
111
|
+
autocompleteMenuRef.current === target ||
|
|
112
|
+
autocompleteMenuRef.current?.contains(target) ||
|
|
113
|
+
wrapperAutocompleteRef.current?.contains(target);
|
|
114
|
+
!wasSomeItemClicked && close();
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const overlayRef = document.querySelector(
|
|
118
|
+
"[data-fs-overlay]"
|
|
119
|
+
) as HTMLElement;
|
|
120
|
+
|
|
121
|
+
document.addEventListener("click", event);
|
|
122
|
+
overlayRef?.addEventListener("click", event);
|
|
123
|
+
|
|
124
|
+
return () => {
|
|
125
|
+
document.removeEventListener("click", event);
|
|
126
|
+
overlayRef.removeEventListener("click", event);
|
|
127
|
+
};
|
|
128
|
+
}, []);
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<AutocompleteDropdownContext.Provider
|
|
132
|
+
value={{
|
|
133
|
+
close,
|
|
134
|
+
focusedItemIndex,
|
|
135
|
+
setFocusedItemIndex: (index: number) => setFocusedItemIndex(index),
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
<div
|
|
139
|
+
data-fs-bp-autocomplete-dropdown
|
|
140
|
+
data-fs-bp-autocomplete-dropdown-only-select={!onChange}
|
|
141
|
+
ref={wrapperAutocompleteRef}
|
|
142
|
+
onClick={handleClick}
|
|
143
|
+
>
|
|
144
|
+
<InputText
|
|
145
|
+
label={label}
|
|
146
|
+
onKeyDown={handleBackdropKeyDown}
|
|
147
|
+
icon={<Icon name="ArrowDropDown" width={20} height={20} />}
|
|
148
|
+
onChange={onChange}
|
|
149
|
+
disabled={disabled}
|
|
150
|
+
hasError={hasError}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
|
|
154
|
+
{isOpened
|
|
155
|
+
? createPortal(
|
|
156
|
+
<div
|
|
157
|
+
data-fs-bp-autocomplete-dropdown-menu
|
|
158
|
+
style={positionStyle}
|
|
159
|
+
ref={autocompleteMenuRef}
|
|
160
|
+
>
|
|
161
|
+
<ul>
|
|
162
|
+
{options?.map((option, index) =>
|
|
163
|
+
renderOption?.(option, index)
|
|
164
|
+
)}
|
|
165
|
+
</ul>
|
|
166
|
+
</div>,
|
|
167
|
+
document.body
|
|
168
|
+
)
|
|
169
|
+
: null}
|
|
170
|
+
</div>
|
|
171
|
+
</AutocompleteDropdownContext.Provider>
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
AutocompleteDropdown.Item = AutocompleteDropdownItem;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ComponentProps, ReactNode } from "react";
|
|
2
|
+
import { useAutocompleteDropdownContext } from "./AutocompleteDropdown";
|
|
3
|
+
|
|
4
|
+
export type AutocompleteDropdownItemProps = ComponentProps<"li"> & {
|
|
5
|
+
isSelected: boolean;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
index: number;
|
|
8
|
+
closeOnClick?: boolean;
|
|
9
|
+
key: string | number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const AutocompleteDropdownItem = ({
|
|
13
|
+
isSelected,
|
|
14
|
+
children,
|
|
15
|
+
index,
|
|
16
|
+
onClick,
|
|
17
|
+
closeOnClick = false,
|
|
18
|
+
...props
|
|
19
|
+
}: AutocompleteDropdownItemProps) => {
|
|
20
|
+
const { focusedItemIndex, setFocusedItemIndex, close } =
|
|
21
|
+
useAutocompleteDropdownContext();
|
|
22
|
+
return (
|
|
23
|
+
<li
|
|
24
|
+
data-fs-bp-autocomplete-dropdown-option
|
|
25
|
+
data-fs-bp-autocomplete-dropdown-option-focused={
|
|
26
|
+
focusedItemIndex === index
|
|
27
|
+
}
|
|
28
|
+
data-fs-bp-autocomplete-dropdown-option-selected={isSelected}
|
|
29
|
+
onMouseEnter={() => setFocusedItemIndex(index)}
|
|
30
|
+
onClick={(e) => {
|
|
31
|
+
closeOnClick && close();
|
|
32
|
+
onClick?.(e);
|
|
33
|
+
}}
|
|
34
|
+
{...props}
|
|
35
|
+
>
|
|
36
|
+
{children}
|
|
37
|
+
</li>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@import "@faststore/ui/src/components/molecules/Dropdown/styles.scss";
|
|
2
|
+
|
|
3
|
+
[data-fs-bp-autocomplete-dropdown] {
|
|
4
|
+
&[data-fs-bp-autocomplete-dropdown-only-select="true"] {
|
|
5
|
+
[data-fs-bp-input-text-input] {
|
|
6
|
+
caret-color: transparent;
|
|
7
|
+
background-color: #ffffff;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
[data-fs-bp-autocomplete-dropdown-menu] {
|
|
13
|
+
padding: var(--fs-spacing-1) 0;
|
|
14
|
+
background-color: #fff;
|
|
15
|
+
box-shadow: 0rem 0.5rem 0.625rem 0rem #00000014;
|
|
16
|
+
|
|
17
|
+
border-radius: calc(var(--fs-border-radius) * 2);
|
|
18
|
+
|
|
19
|
+
[data-fs-bp-autocomplete-dropdown-option] {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: space-between;
|
|
23
|
+
|
|
24
|
+
width: 100%;
|
|
25
|
+
|
|
26
|
+
font-size: var(--fs-text-size-1);
|
|
27
|
+
font-weight: 500;
|
|
28
|
+
line-height: calc(var(--fs-spacing-3) + var(--fs-spacing-0));
|
|
29
|
+
|
|
30
|
+
color: #3d3d3d;
|
|
31
|
+
|
|
32
|
+
padding: var(--fs-spacing-1) calc(var(--fs-spacing-3) + var(--fs-spacing-0));
|
|
33
|
+
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
|
|
36
|
+
&[data-fs-bp-autocomplete-dropdown-option-focused="true"] {
|
|
37
|
+
background-color: #f5f5f5;
|
|
38
|
+
color: #3d3d3d;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&[data-fs-bp-autocomplete-dropdown-option-selected="true"] {
|
|
42
|
+
color: #0366dd;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|