@vtex/faststore-plugin-buyer-portal 1.3.77 → 1.3.78

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/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.3.78] - 2026-04-23
11
+
12
+ ### Changed
13
+ - Move addresses list requests from server to client side
14
+
15
+ ### Fixed
16
+ - Remove `for` loop from `AddressesClient.getAddressesByUnitId` to prevent failed requests
17
+
10
18
  ## [1.3.77] - 2026-04-14
11
19
 
12
20
  ### Changed
@@ -573,7 +581,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
573
581
  - Add CHANGELOG file
574
582
  - Add README file
575
583
 
576
- [unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.77...HEAD
584
+ [unreleased]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.78...HEAD
577
585
  [1.3.55]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.54...v1.3.55
578
586
  [1.3.54]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.53...v1.3.54
579
587
  [1.3.53]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.52...v1.3.53
@@ -641,6 +649,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
641
649
  [1.3.65]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.64...v1.3.65
642
650
  [1.3.64]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.3.64
643
651
  [1.3.69]: https://github.com/vtex/faststore-plugin-buyer-portal/releases/tag/1.3.69
652
+ [1.3.78]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.77...v1.3.78
644
653
  [1.3.77]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.76...v1.3.77
645
654
  [1.3.76]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.75...v1.3.76
646
655
  [1.3.75]: https://github.com/vtex/faststore-plugin-buyer-portal/compare/v1.3.74...v1.3.75
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.3.77",
3
+ "version": "1.3.78",
4
4
  "description": "A plugin for faststore with buyer portal",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -32,32 +32,14 @@ export default class AddressesClient extends Client {
32
32
  addressType,
33
33
  page = 1,
34
34
  }: GetAddressesByUnitIdParams) {
35
- let allAddresses: AddressData[] = [];
36
- let total = 0;
37
-
38
- for (let currentPage = 1; currentPage <= page; currentPage++) {
39
- const params = new URLSearchParams();
40
- if (name) params.append("name", name);
41
- if (currentPage > 1) params.append("page", String(currentPage));
42
- if (addressType) params.append("addressType", addressType);
43
- const queryString = params.toString();
44
- const url = queryString
45
- ? `units/${orgUnitId}/addresses?${queryString}`
46
- : `units/${orgUnitId}/addresses`;
47
-
48
- const response = await this.get<AddressResponse>(url, {
49
- headers: {
50
- Cookie: cookie,
51
- },
52
- });
53
-
54
- if (response?.addresses) {
55
- allAddresses = allAddresses.concat(response.addresses);
56
- total = response.total;
57
- }
58
- }
59
-
60
- return { addresses: allAddresses, total };
35
+ return this.get<AddressResponse>(`units/${orgUnitId}/addresses`, {
36
+ headers: { Cookie: cookie },
37
+ params: {
38
+ page,
39
+ name: name ?? "",
40
+ addressType: addressType ?? "",
41
+ },
42
+ });
61
43
  }
62
44
 
63
45
  getAddressById(
@@ -8,3 +8,4 @@ export * from "./useAddressLocationDelete";
8
8
  export * from "./useSetDefaultAddress";
9
9
  export * from "./useUnsetDefaultAddress";
10
10
  export * from "./useGetDefaultAddresses";
11
+ export * from "./useListAddresses";
@@ -1,7 +1,7 @@
1
1
  import { useDebounce } from "../../shared/hooks";
2
2
  import { DEBOUNCE_TIMEOUT } from "../../shared/utils/constants";
3
3
 
4
- import { useSearchAddressByUnitId } from "./useSearchAddressByUnitId";
4
+ import { useListAddresses } from "./useListAddresses";
5
5
 
6
6
  import type { AddressData } from "../types";
7
7
  import type { UseDebouncedSearchAddressByUnitIdProps } from "../types/AddressData";
@@ -12,12 +12,11 @@ export const useDebouncedSearchAddressByUnitId = ({
12
12
  addressType,
13
13
  }: UseDebouncedSearchAddressByUnitIdProps) => {
14
14
  const debouncedSearchTerm = useDebounce(search, DEBOUNCE_TIMEOUT);
15
- const { searchedAddresses, isSearchedAddressesLoading } =
16
- useSearchAddressByUnitId({
17
- orgUnitId,
18
- search: debouncedSearchTerm,
19
- addressType,
20
- });
15
+ const { listAddressesData, listAddressesLoading } = useListAddresses({
16
+ orgUnitId,
17
+ search: debouncedSearchTerm,
18
+ addressType,
19
+ });
21
20
 
22
21
  if (search === "") {
23
22
  return {
@@ -27,7 +26,7 @@ export const useDebouncedSearchAddressByUnitId = ({
27
26
  }
28
27
 
29
28
  return {
30
- searchedAddresses: searchedAddresses?.data ?? [],
31
- isDebouncedSearchAddressesLoading: isSearchedAddressesLoading,
29
+ searchedAddresses: listAddressesData?.data ?? [],
30
+ isDebouncedSearchAddressesLoading: listAddressesLoading,
32
31
  };
33
32
  };
@@ -0,0 +1,36 @@
1
+ import { type QueryOptions, useQuery } from "../../shared/hooks";
2
+ import { getAddressesByUnitIdService } from "../services";
3
+
4
+ type UseListAddressesProps = {
5
+ orgUnitId: string;
6
+ search: string;
7
+ page?: number;
8
+ addressType?: string;
9
+ };
10
+
11
+ export const useListAddresses = (
12
+ { orgUnitId, search, page = 1, addressType }: UseListAddressesProps,
13
+ options?: QueryOptions<AwaitedType<typeof getAddressesByUnitIdService>>
14
+ ) => {
15
+ const { data, error, isLoading, refetch } = useQuery(
16
+ `api/addresses/unitId=${orgUnitId}/page=${page}/search=${
17
+ search ?? ""
18
+ }/addressType=${addressType ?? ""}`,
19
+ ({ cookie }) =>
20
+ getAddressesByUnitIdService({
21
+ orgUnitId,
22
+ search,
23
+ cookie,
24
+ addressType,
25
+ page,
26
+ }),
27
+ options
28
+ );
29
+
30
+ return {
31
+ listAddressesData: data,
32
+ listAddressesError: error,
33
+ listAddressesLoading: isLoading,
34
+ listAddressesRefresh: refetch,
35
+ };
36
+ };
@@ -3,85 +3,42 @@ import { useEffect } from "react";
3
3
  import { useRouter } from "next/router";
4
4
 
5
5
  import {
6
+ EmptyState,
6
7
  HeaderInside,
7
8
  IconBookmarked,
8
9
  InternalSearch,
9
10
  Paginator,
11
+ Table,
10
12
  } from "../../../shared/components";
11
- import { EmptyState } from "../../../shared/components/EmptyState/EmptyState";
12
- import { Table } from "../../../shared/components/Table/Table";
13
13
  import { getTableColumns } from "../../../shared/components/Table/utils/tableColumns";
14
14
  import {
15
15
  useBuyerPortal,
16
16
  useDrawerProps,
17
17
  useGetScopeConfig,
18
+ useUrlPaginatedSearch,
18
19
  SCOPE_KEYS,
19
20
  } from "../../../shared/hooks";
20
- import { usePageItems } from "../../../shared/hooks/usePageItems";
21
21
  import { ContractTabsLayout, GlobalLayout } from "../../../shared/layouts";
22
22
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
23
23
  import { AddressDropdownMenu, CreateAddressDrawer } from "../../components";
24
24
  import { CreateAddressSettingsDrawer } from "../../components/CreateAddressSettingsDrawer/CreateAddressSettingsDrawer";
25
- import { useSearchAddressByUnitId } from "../../hooks/useSearchAddressByUnitId";
25
+ import { useListAddresses } from "../../hooks/useListAddresses";
26
26
 
27
- import type { AddressData } from "../../types";
27
+ const PAGE_SIZE = 25;
28
28
 
29
- export type AddressLayoutProps = {
30
- addresses: AddressData[];
31
- total: number;
32
- search: string;
33
- page: number;
34
- };
35
-
36
- export const AddressLayout = ({
37
- addresses: initialAddresses,
38
- search,
39
- total,
40
- page,
41
- }: AddressLayoutProps) => {
29
+ export const AddressLayout = () => {
42
30
  const router = useRouter();
43
31
 
44
32
  const {
45
- isLoading,
46
- items: addresses,
47
- searchTerm,
48
- setSearchTerm,
49
- increasePage,
50
- updateItemsFromRefetch,
51
- setIsLoading,
52
- } = usePageItems<AddressData>({
53
- initialItems: initialAddresses,
54
- search,
55
33
  page,
56
- });
57
-
58
- const { searchedAddresses: addressesData, refetchSearchedAddresses } =
59
- useSearchAddressByUnitId(
60
- {
61
- orgUnitId: router.query.orgUnitId as string,
62
- search: search ?? "",
63
- },
64
- { lazy: true }
65
- );
66
-
67
- useEffect(() => {
68
- if (addresses.length === 0) {
69
- setIsLoading(true);
70
- refetchSearchedAddresses();
71
- }
72
- }, []);
73
-
74
- useEffect(() => {
75
- if (addressesData?.data) {
76
- updateItemsFromRefetch(addressesData.data);
77
- }
78
- }, [addressesData]);
79
-
80
- const handleRefetchAddresses = () => {
81
- setIsLoading(true);
82
- refetchScopeConfig();
83
- refetchSearchedAddresses();
84
- };
34
+ search,
35
+ committedSearch,
36
+ isRouterSynced,
37
+ setSearch,
38
+ goToPage,
39
+ nextPage,
40
+ previousPage,
41
+ } = useUrlPaginatedSearch();
85
42
 
86
43
  const {
87
44
  open: openCreateDrawer,
@@ -109,6 +66,21 @@ export const AddressLayout = ({
109
66
  }
110
67
  );
111
68
 
69
+ const { listAddressesData, listAddressesLoading, listAddressesRefresh } =
70
+ useListAddresses(
71
+ {
72
+ orgUnitId: (router.query.orgUnitId as string) ?? "",
73
+ page: isRouterSynced ? page : 0,
74
+ search: committedSearch,
75
+ },
76
+ { lazy: !isRouterSynced }
77
+ );
78
+
79
+ const handleRefetchAddresses = () => {
80
+ refetchScopeConfig();
81
+ listAddressesRefresh();
82
+ };
83
+
112
84
  const columns = getTableColumns({
113
85
  nameColumnSize: "18.125rem",
114
86
  actionsLength: 2,
@@ -123,6 +95,23 @@ export const AddressLayout = ({
123
95
  ],
124
96
  });
125
97
 
98
+ const intervalData = {
99
+ page,
100
+ itemsLength: listAddressesData?.data.length ?? 0,
101
+ total: listAddressesData?.total ?? 0,
102
+ isLoading: listAddressesLoading,
103
+ };
104
+
105
+ const totalPages = Math.ceil(intervalData.total / PAGE_SIZE);
106
+
107
+ useEffect(() => {
108
+ if (listAddressesLoading || intervalData.total === 0) return;
109
+
110
+ if (page > totalPages) {
111
+ goToPage(Math.max(totalPages, 1));
112
+ }
113
+ }, [page, totalPages, intervalData.total, listAddressesLoading]);
114
+
126
115
  return (
127
116
  <GlobalLayout>
128
117
  <ContractTabsLayout
@@ -142,103 +131,96 @@ export const AddressLayout = ({
142
131
  <HeaderInside.Button onClick={openCreateDrawer} />
143
132
  </HeaderInside>
144
133
 
145
- {addresses.length === 0 && !isLoading && searchTerm.length === 0 ? (
146
- <EmptyState title="No addresses yet" iconName="LocalPostOffice" />
134
+ <div data-fs-buyer-portal-address-filter>
135
+ <InternalSearch defaultValue={search} textSearch={setSearch} />
136
+ <Paginator.Interval {...intervalData} />
137
+ </div>
138
+
139
+ {!listAddressesLoading && intervalData.total === 0 ? (
140
+ <EmptyState
141
+ title={
142
+ committedSearch.length > 0
143
+ ? "No results found"
144
+ : "No addresses yet"
145
+ }
146
+ description={
147
+ committedSearch.length > 0
148
+ ? "Try using different terms or filters"
149
+ : undefined
150
+ }
151
+ iconName={
152
+ committedSearch.length > 0 ? undefined : "LocalPostOffice"
153
+ }
154
+ />
147
155
  ) : (
148
- <>
149
- <div data-fs-buyer-portal-address-filter>
150
- <InternalSearch
151
- defaultValue={searchTerm}
152
- textSearch={setSearchTerm}
153
- />
154
- <div data-fs-bp-top-counter>
155
- <Paginator.Counter
156
- total={total}
157
- itemsLength={addresses.length}
158
- />
159
- </div>
160
- </div>
161
- {!isLoading && addresses.length === 0 && searchTerm.length > 0 ? (
162
- <EmptyState
163
- title="No results found"
164
- description="Try using different terms or filters"
165
- />
166
- ) : (
167
- <div data-fs-addresses-table>
168
- <Table layoutFixed>
169
- <Table.Head columns={columns} />
170
-
171
- <Table.Body>
172
- {isLoading ? (
173
- <Table.Loading columns={columns.length} />
174
- ) : (
175
- addresses.map(({ id, ...address }) => (
176
- <Table.Row
177
- key={id}
178
- title={address.name}
179
- searchTerm={search}
180
- iconName="LocalPostOffice"
181
- iconSize={20}
182
- children={
183
- <Table.Cell hideOnScreenSize="phonemid">
184
- {Array.isArray(address.types) &&
185
- address.types.length > 0 ? (
186
- <span>{address.types.join(", ")}</span>
187
- ) : null}
188
- </Table.Cell>
189
- }
190
- href={buyerPortalRoutes.addressDetails({
191
- orgUnitId: orgUnit?.id ?? "",
192
- contractId: contract?.id ?? "",
193
- addressId: id,
194
- })}
195
- actionIcons={
196
- address.isDefault ? <IconBookmarked /> : null
197
- }
198
- dropdownMenu={
199
- <AddressDropdownMenu
200
- currentAddress={{
201
- id,
202
- ...address,
203
- }}
204
- isSyncMode={isSyncMode}
205
- onUpdate={handleRefetchAddresses}
206
- onOpen={() => {
207
- const url = buyerPortalRoutes.addressDetails({
208
- orgUnitId: orgUnit?.id ?? "",
209
- contractId: contract?.id ?? "",
210
- addressId: id,
211
- });
212
-
213
- router.push(url);
214
- }}
215
- />
216
- }
156
+ <div data-fs-addresses-table>
157
+ <Table layoutFixed>
158
+ <Table.Head columns={columns} />
159
+ <Table.Body>
160
+ {listAddressesLoading ? (
161
+ <Table.Loading columns={columns.length} />
162
+ ) : (
163
+ listAddressesData?.data.map(({ id, ...address }) => (
164
+ <Table.Row
165
+ key={id}
166
+ title={address.name}
167
+ searchTerm={committedSearch}
168
+ iconName="LocalPostOffice"
169
+ iconSize={20}
170
+ href={buyerPortalRoutes.addressDetails({
171
+ orgUnitId: orgUnit?.id ?? "",
172
+ contractId: contract?.id ?? "",
173
+ addressId: id,
174
+ })}
175
+ actionIcons={
176
+ address.isDefault ? <IconBookmarked /> : null
177
+ }
178
+ dropdownMenu={
179
+ <AddressDropdownMenu
180
+ currentAddress={{ id, ...address }}
181
+ isSyncMode={isSyncMode}
182
+ onUpdate={handleRefetchAddresses}
183
+ onOpen={() => {
184
+ const url = buyerPortalRoutes.addressDetails({
185
+ orgUnitId: orgUnit?.id ?? "",
186
+ contractId: contract?.id ?? "",
187
+ addressId: id,
188
+ });
189
+
190
+ router.push(url);
191
+ }}
217
192
  />
218
- ))
219
- )}
220
- </Table.Body>
221
- </Table>
222
-
223
- {!isLoading && (
224
- <p
225
- data-fs-bp-addresses-paginator-last
226
- >{`${addresses.length} of ${total}`}</p>
227
- )}
228
-
229
- <div data-fs-bp-addresses-paginator>
230
- {total > addresses.length && (
231
- <Paginator.NextPageButton
232
- onClick={increasePage}
233
- disabled={isLoading}
193
+ }
234
194
  >
235
- {isLoading ? "Loading" : "Load More"}
236
- </Paginator.NextPageButton>
237
- )}
238
- </div>
239
- </div>
240
- )}
241
- </>
195
+ <Table.Cell hideOnScreenSize="phonemid">
196
+ {Array.isArray(address.types) &&
197
+ address.types.length > 0 ? (
198
+ <span>{address.types.join(", ")}</span>
199
+ ) : null}
200
+ </Table.Cell>
201
+ </Table.Row>
202
+ ))
203
+ )}
204
+ </Table.Body>
205
+ </Table>
206
+
207
+ <div data-fs-bp-addresses-paginator>
208
+ <Paginator.NextPageButton
209
+ onClick={previousPage}
210
+ disabled={page <= 1}
211
+ >
212
+ Previous Page
213
+ </Paginator.NextPageButton>
214
+ <Paginator.NextPageButton
215
+ data-fs-bp-addresses-next-page
216
+ onClick={nextPage}
217
+ disabled={page >= totalPages}
218
+ >
219
+ Next Page
220
+ </Paginator.NextPageButton>
221
+ <Paginator.Interval {...intervalData} />
222
+ </div>
223
+ </div>
242
224
  )}
243
225
 
244
226
  {isCreateAddressDrawerOpen && (
@@ -146,8 +146,23 @@
146
146
  display: flex;
147
147
  align-items: center;
148
148
  justify-content: flex-start;
149
- margin-top: var(--fs-spacing-2);
150
- padding: var(--fs-spacing-2) 0;
149
+ margin-top: var(--fs-bp-margin-3);
150
+ padding: var(--fs-bp-padding-3) 0;
151
+ gap: var(--fs-bp-gap-4);
152
+
153
+ [data-fs-bp-paginator-counter] {
154
+ margin-left: var(--fs-bp-margin-auto)
155
+ }
156
+
157
+ [data-fs-paginator-next-page-button]:disabled {
158
+ cursor: not-allowed;
159
+ color: var(--fs-bp-color-neutral-6);
160
+
161
+ &:hover {
162
+ color: var(--fs-bp-color-neutral-6);
163
+ background-color: transparent;
164
+ }
165
+ }
151
166
 
152
167
  @include media("<=phonemid") {
153
168
  padding: var(--fs-spacing-3) 0;
@@ -2,7 +2,4 @@ export {
2
2
  AddressDetailsLayout,
3
3
  type AddressDetailsLayoutProps,
4
4
  } from "./AddressDetailsLayout/AddressDetailsLayout";
5
- export {
6
- AddressLayout,
7
- type AddressLayoutProps,
8
- } from "./AddressesLayout/AddressesLayout";
5
+ export { AddressLayout } from "./AddressesLayout/AddressesLayout";
@@ -18,3 +18,4 @@ export { useAnalytics } from "./analytics/useAnalytics";
18
18
  export { ANALYTICS_FALLBACK_CORRELATION_ID } from "./analytics/constants";
19
19
  export { useGetScopeConfig, SCOPE_KEYS } from "./useGetScopeConfig";
20
20
  export { useSetScopeConfig } from "./useSetScopeConfig";
21
+ export { useUrlPaginatedSearch } from "./useUrlPaginatedSearch";
@@ -0,0 +1,79 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ import { useRouter } from "next/router";
4
+
5
+ import { getValidPage } from "../utils";
6
+
7
+ import { useDebounce } from "./useDebounce";
8
+ import { useQueryParams } from "./useQueryParams";
9
+
10
+ type UseUrlPaginatedSearchOptions = {
11
+ pageParam?: string;
12
+ searchParam?: string;
13
+ debounceMs?: number;
14
+ };
15
+
16
+ export function useUrlPaginatedSearch(options?: UseUrlPaginatedSearchOptions) {
17
+ const {
18
+ pageParam = "page",
19
+ searchParam = "search",
20
+ debounceMs = 300,
21
+ } = options ?? {};
22
+
23
+ const router = useRouter();
24
+ const { setQueryStrings } = useQueryParams();
25
+
26
+ const [page, setPageState] = useState(1);
27
+ const [search, setSearch] = useState("");
28
+ const [committedSearch, setCommittedSearch] = useState("");
29
+ const [isRouterSynced, setIsRouterSynced] = useState(false);
30
+
31
+ useEffect(() => {
32
+ if (!router.isReady) return;
33
+
34
+ const urlPage = getValidPage(router.query[pageParam]);
35
+ const urlSearch = (router.query[searchParam] ?? "").toString();
36
+
37
+ setPageState(urlPage);
38
+ setSearch(urlSearch);
39
+ setCommittedSearch(urlSearch);
40
+ setIsRouterSynced(true);
41
+ }, [router.isReady, router.query[pageParam], router.query[searchParam]]);
42
+
43
+ useDebounce(search, debounceMs, {
44
+ onDebounce: (value) => {
45
+ setCommittedSearch((prev) => {
46
+ if (value === prev) return prev;
47
+
48
+ setPageState(1);
49
+ setQueryStrings({
50
+ [pageParam]: "1",
51
+ [searchParam]: value || null,
52
+ });
53
+
54
+ return value;
55
+ });
56
+ },
57
+ });
58
+
59
+ const goToPage = (newPage: number) => {
60
+ setPageState(() => {
61
+ setQueryStrings({ [pageParam]: `${newPage}` });
62
+ return newPage;
63
+ });
64
+ };
65
+
66
+ const nextPage = () => goToPage(page + 1);
67
+ const previousPage = () => goToPage(page - 1);
68
+
69
+ return {
70
+ page,
71
+ search,
72
+ committedSearch,
73
+ isRouterSynced,
74
+ setSearch,
75
+ goToPage,
76
+ nextPage,
77
+ previousPage,
78
+ };
79
+ }
@@ -22,4 +22,4 @@ export const SCOPE_KEYS = {
22
22
  CREDIT_CARDS: "creditCards",
23
23
  } as const;
24
24
 
25
- export const CURRENT_VERSION = "1.3.77";
25
+ export const CURRENT_VERSION = "1.3.78";
@@ -1,8 +1,4 @@
1
1
  import { AddressLayout } from "../features/addresses/layouts";
2
- import {
3
- getAddressesByUnitIdService,
4
- type GetAddressesServiceProps,
5
- } from "../features/addresses/services";
6
2
  import { getContractDetailsService } from "../features/contracts/services";
7
3
  import { getOrgUnitBasicDataService } from "../features/org-units/services";
8
4
  import { withErrorBoundary } from "../features/shared/components";
@@ -10,24 +6,18 @@ import { ErrorBoundaryProps } from "../features/shared/components/ErrorBoundary/
10
6
  import { ErrorTabsLayout } from "../features/shared/layouts/ErrorTabsLayout/ErrorTabsLayout";
11
7
  import {
12
8
  type ClientContext,
13
- getValidPage,
14
9
  withLoaderErrorBoundary,
15
10
  withAuthLoader,
16
11
  withProviders,
17
12
  } from "../features/shared/utils";
18
13
  import { getUserByIdService } from "../features/users/services";
19
14
 
20
- import type { AddressData } from "../features/addresses/types";
21
15
  import type { ContractData } from "../features/contracts/types";
22
16
  import type { OrgUnitBasicData } from "../features/org-units/types";
23
17
  import type { AuthRouteProps, LoaderData } from "../features/shared/types";
24
18
  import type { UserData } from "../features/users/types";
25
19
 
26
20
  export type AddressesPageData = {
27
- data: AddressData[];
28
- search: string;
29
- total: number;
30
- page: number;
31
21
  context: {
32
22
  currentContract: ContractData | null;
33
23
  clientContext: ClientContext;
@@ -38,28 +28,21 @@ export type AddressesPageData = {
38
28
  error?: ErrorBoundaryProps;
39
29
  };
40
30
 
41
- export type AddressesPageQuery = GetAddressesServiceProps & {
31
+ export type AddressesPageQuery = {
42
32
  orgUnitId: string;
43
33
  contractId: string;
44
- page?: string;
45
34
  };
46
35
 
47
36
  const loaderFunction = async (
48
37
  data: LoaderData<AddressesPageQuery>
49
38
  ): Promise<AuthRouteProps<AddressesPageData>> => {
50
- const { contractId, orgUnitId, search, page: pageString } = data.query;
51
-
52
- const page = getValidPage(pageString);
39
+ const { contractId, orgUnitId } = data.query;
53
40
 
54
41
  return withAuthLoader(
55
42
  data,
56
43
  async ({ cookie, userId, customerId, ...clientContext }) => {
57
44
  if (!contractId || !orgUnitId) {
58
45
  return {
59
- data: [],
60
- search: search ?? "",
61
- total: 0,
62
- page: page ?? 1,
63
46
  context: {
64
47
  clientContext: { customerId, cookie, userId, ...clientContext },
65
48
  currentOrgUnit: null,
@@ -69,31 +52,20 @@ const loaderFunction = async (
69
52
  };
70
53
  }
71
54
 
72
- const [currentOrgUnit, user, contract, addressesResponse] =
73
- await Promise.all([
74
- getOrgUnitBasicDataService({
75
- id: orgUnitId,
76
- cookie,
77
- }),
78
- getUserByIdService({ orgUnitId, userId, cookie }),
79
- getContractDetailsService({
80
- contractId,
81
- cookie,
82
- unitId: orgUnitId,
83
- }),
84
- getAddressesByUnitIdService({
85
- orgUnitId,
86
- search,
87
- page,
88
- cookie,
89
- }),
90
- ]);
55
+ const [currentOrgUnit, user, contract] = await Promise.all([
56
+ getOrgUnitBasicDataService({
57
+ id: orgUnitId,
58
+ cookie,
59
+ }),
60
+ getUserByIdService({ orgUnitId, userId, cookie }),
61
+ getContractDetailsService({
62
+ contractId,
63
+ cookie,
64
+ unitId: orgUnitId,
65
+ }),
66
+ ]);
91
67
 
92
68
  return {
93
- data: addressesResponse.data,
94
- total: addressesResponse.total,
95
- page,
96
- search: search ?? "",
97
69
  context: {
98
70
  clientContext: { cookie, userId, customerId, ...clientContext },
99
71
  currentOrgUnit,
@@ -110,26 +82,8 @@ export const loader = withLoaderErrorBoundary(loaderFunction, {
110
82
  redirectToError: true,
111
83
  });
112
84
 
113
- const AddressPage = ({
114
- data,
115
- search,
116
- page,
117
- total,
118
- hasError,
119
- error,
120
- }: AddressesPageData) => (
121
- <>
122
- {hasError ? (
123
- <ErrorTabsLayout error={error} />
124
- ) : (
125
- <AddressLayout
126
- addresses={data}
127
- search={search}
128
- page={page}
129
- total={total}
130
- />
131
- )}
132
- </>
85
+ const AddressPage = ({ hasError, error }: AddressesPageData) => (
86
+ <>{hasError ? <ErrorTabsLayout error={error} /> : <AddressLayout />}</>
133
87
  );
134
88
 
135
89
  export default withProviders(
@@ -1,27 +0,0 @@
1
- import { type QueryOptions, useQuery } from "../../shared/hooks";
2
- import { getAddressesByUnitIdService } from "../services";
3
-
4
- import type { UseDebouncedSearchAddressByUnitIdProps } from "../types/AddressData";
5
-
6
- export const useSearchAddressByUnitId = (
7
- { orgUnitId, search, addressType }: UseDebouncedSearchAddressByUnitIdProps,
8
- options?: QueryOptions<AwaitedType<typeof getAddressesByUnitIdService>>
9
- ) => {
10
- const { data, error, isLoading, refetch } = useQuery(
11
- `api/search/addresses/${search}`,
12
- ({ cookie }) =>
13
- getAddressesByUnitIdService({
14
- orgUnitId,
15
- search,
16
- cookie,
17
- addressType,
18
- }),
19
- options
20
- );
21
- return {
22
- searchedAddresses: data,
23
- hasSearchedAddressesError: error,
24
- isSearchedAddressesLoading: isLoading,
25
- refetchSearchedAddresses: refetch,
26
- };
27
- };