diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 044c66c6..f4dd9d2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -252,6 +252,9 @@ importers: '@tailwindcss/postcss': specifier: ^4 version: 4.2.4 + '@testing-library/dom': + specifier: ^10.4.1 + version: 10.4.1 '@testing-library/jest-dom': specifier: ^6.5.0 version: 6.9.1 @@ -314,7 +317,7 @@ importers: version: 10.3.5(eslint@9.39.4(jiti@2.6.1))(storybook@10.3.5(@testing-library/dom@10.4.1)(bufferutil@4.1.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(utf-8-validate@5.0.10))(typescript@5.9.3) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.19.39) + version: 29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) jest-axe: specifier: ^10.0.0 version: 10.0.0 @@ -336,11 +339,14 @@ importers: tailwindcss: specifier: ^4.1.4 version: 4.2.4 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.19.39)(typescript@5.9.3) tw-animate-css: specifier: ^1.4.0 version: 1.4.0 typescript: - specifier: ^5 + specifier: ^5.9.3 version: 5.9.3 vite: specifier: ^8.0.3 @@ -565,6 +571,10 @@ packages: '@coinbase/wallet-sdk@4.3.7': resolution: {integrity: sha512-z6e5XDw6EF06RqkeyEa+qD0dZ2ZbLci99vx3zwDY//XO8X7166tqKJrR2XlQnzVmtcUuJtCd5fCvr9Cu6zzX7w==} + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@cypress/react@9.0.2': resolution: {integrity: sha512-b20a0g6Ot3u92wdmDD+4/r5NkAKPJz+yN2miuydDwy63Hzpk9fLQ0tee5xzx/0VPxYrh3dzedoO8dwUR3qpBlg==} peerDependencies: @@ -1142,6 +1152,9 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@mdx-js/react@3.1.1': resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} peerDependencies: @@ -2458,6 +2471,18 @@ packages: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -3160,6 +3185,9 @@ packages: arch@2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -3682,6 +3710,9 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-fetch@2.2.6: resolution: {integrity: sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA==} @@ -3912,6 +3943,10 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} + engines: {node: '>=0.3.1'} + dijkstrajs@1.0.3: resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} @@ -5487,6 +5522,9 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} @@ -6748,6 +6786,20 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + tsconfck@3.1.6: resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} @@ -6934,6 +6986,9 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + v8-to-istanbul@9.3.0: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} @@ -7299,6 +7354,10 @@ packages: yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -7606,6 +7665,10 @@ snapshots: - utf-8-validate - zod + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + '@cypress/react@9.0.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(cypress@15.14.1)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@types/react-dom': 19.2.3(@types/react@19.2.14) @@ -7992,7 +8055,7 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -8006,7 +8069,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.19.39) + jest-config: 29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -8172,6 +8235,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: '@types/mdx': 2.0.13 @@ -9507,6 +9575,14 @@ snapshots: '@tootallnate/once@2.0.0': {} + '@tsconfig/node10@1.0.12': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -10287,6 +10363,8 @@ snapshots: arch@2.2.0: {} + arg@4.1.3: {} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -10844,13 +10922,13 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.12 - create-jest@29.7.0(@types/node@20.19.39): + create-jest@29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.19.39) + jest-config: 29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -10859,6 +10937,8 @@ snapshots: - supports-color - ts-node + create-require@1.1.1: {} + cross-fetch@2.2.6: dependencies: node-fetch: 2.7.0 @@ -11094,6 +11174,8 @@ snapshots: diff-sequences@29.6.3: {} + diff@4.0.4: {} + dijkstrajs@1.0.3: {} doctrine@2.1.0: @@ -12548,16 +12630,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.19.39): + jest-cli@29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.19.39) + create-jest: 29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.19.39) + jest-config: 29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -12567,7 +12649,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.19.39): + jest-config@29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)): dependencies: '@babel/core': 7.29.0 '@jest/test-sequencer': 29.7.0 @@ -12593,6 +12675,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.19.39 + ts-node: 10.9.2(@types/node@20.19.39)(typescript@5.9.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -12834,12 +12917,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.19.39): + jest@29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.19.39) + jest-cli: 29.7.0(@types/node@20.19.39)(ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -13178,6 +13261,8 @@ snapshots: dependencies: semver: 7.7.4 + make-error@1.3.6: {} + makeerror@1.0.12: dependencies: tmpl: 1.0.5 @@ -14542,6 +14627,24 @@ snapshots: ts-dedent@2.2.0: {} + ts-node@10.9.2(@types/node@20.19.39)(typescript@5.9.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.19.39 + acorn: 8.16.0 + acorn-walk: 8.3.5 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.4 + make-error: 1.3.6 + typescript: 5.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + tsconfck@3.1.6(typescript@5.9.3): optionalDependencies: typescript: 5.9.3 @@ -14750,6 +14853,8 @@ snapshots: uuid@9.0.1: {} + v8-compile-cache-lib@3.0.1: {} + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -15154,6 +15259,8 @@ snapshots: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 + yn@3.1.1: {} + yocto-queue@0.1.0: {} zod-validation-error@4.0.2(zod@4.3.6): diff --git a/src/app/properties/page.tsx b/src/app/properties/page.tsx index 0d8b9d57..82a2b89b 100644 --- a/src/app/properties/page.tsx +++ b/src/app/properties/page.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { Suspense, useEffect } from "react"; +import React, { Suspense, useCallback, useEffect } from "react"; import { SearchFilterForm } from "@/components/forms/SearchFilterForm"; import { SearchResults } from "@/components/SearchResults"; import { WalletConnector } from "@/components/WalletConnector"; @@ -13,6 +13,7 @@ import { useWalletStore } from "@/store/walletStore"; import { useNotificationChecker } from "@/hooks/useNotificationChecker"; import { useFavoritesStore } from "@/store/favoritesStore"; import { usePaginationParams, isValidPageSize, type PageSize } from "@/hooks/usePaginationParams"; +import type { SortOption } from "@/types/property"; import Link from "next/link"; import { Heart } from "lucide-react"; import PropertyPageSkeleton from "@/components/PropertyPageSkeleton"; @@ -29,7 +30,6 @@ function PropertiesContent() { // Ensure viewMode is only 'grid' or 'list' for now (map view not implemented yet) const viewMode: "grid" | "list" = storeViewMode === "map" ? "grid" : storeViewMode; - const setViewMode = (mode: "grid" | "list") => setStoreViewMode(mode); const { favorites } = useFavoritesStore(); @@ -68,14 +68,33 @@ function PropertiesContent() { }, [urlSize]); // eslint-disable-line react-hooks/exhaustive-deps // Page change: update URL (which triggers the effect above to sync the store) - const handlePageChange = (newPage: number) => { + const handlePageChange = useCallback((newPage: number) => { setUrlPage(newPage); - }; + }, [setUrlPage]); // Page size change: update URL (resets to page 1 inside setUrlSize) - const handlePageSizeChange = (newSize: PageSize) => { + const handlePageSizeChange = useCallback((newSize: PageSize) => { setUrlSize(newSize); - }; + }, [setUrlSize]); + + const handleSortChange = useCallback((newSort: SortOption) => { + setSortBy(newSort); + setUrlPage(1); + }, [setSortBy, setUrlPage]); + + const handleViewModeChange = useCallback((mode: "grid" | "list") => { + setStoreViewMode(mode); + }, [setStoreViewMode]); + + const handleApplyFilters = useCallback((newFilters: typeof filters) => { + setFilters(newFilters); + setUrlPage(1); + }, [setFilters, setUrlPage]); + + const handleClearFilters = useCallback(() => { + clearFilters(); + setUrlPage(1); + }, [clearFilters, setUrlPage]); return (
+
• {warning}
))} @@ -254,7 +254,7 @@ export const SecureTransactionConfirmation: React.FC+
• {risk}
))} diff --git a/src/components/TransactionConfirmation.tsx b/src/components/TransactionConfirmation.tsx index 383fa14a..13f5cfdf 100644 --- a/src/components/TransactionConfirmation.tsx +++ b/src/components/TransactionConfirmation.tsx @@ -370,7 +370,7 @@ export const TransactionConfirmation: React.FC+
• {warning}
))} @@ -390,7 +390,7 @@ export const TransactionConfirmation: React.FC+
• {block}
))} diff --git a/src/components/WalletConnectedView.tsx b/src/components/WalletConnectedView.tsx index 6c17ddad..c2fead89 100644 --- a/src/components/WalletConnectedView.tsx +++ b/src/components/WalletConnectedView.tsx @@ -62,7 +62,7 @@ interface WalletConnectedViewProps { * - Disconnect button * - Error messages */ -export function WalletConnectedView({ address }: WalletConnectedViewProps) { +const WalletConnectedViewInner: React.FC+
• {block}
))} @@ -105,7 +105,7 @@ export const WalletModal: React.FC+
• {warning}
))}