Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 46 additions & 9 deletions src/components/BridgeFilterSort.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,53 @@
import {
useBridgeFilterSortStore,
type BridgeSortBy,
type BridgeStatusFilter,
} from "../stores/bridgeFilterSortStore";

interface BridgeFilterSortProps {
statusFilter: string;
onStatusFilterChange: (status: string) => void;
sortBy: string;
onSortByChange: (sortBy: string) => void;
/** Optional controlled status filter; defaults to the persisted store value. */
statusFilter?: string;
onStatusFilterChange?: (status: string) => void;
/** Optional controlled sort key; defaults to the persisted store value. */
sortBy?: string;
onSortByChange?: (sortBy: string) => void;
}

/**
* Bridge status filter + sort controls.
* Selections are persisted to localStorage via `useBridgeFilterSortStore`
* unless fully controlled by the parent through props.
*/
export default function BridgeFilterSort({
statusFilter,
statusFilter: statusFilterProp,
onStatusFilterChange,
sortBy,
sortBy: sortByProp,
onSortByChange,
}: BridgeFilterSortProps) {
}: BridgeFilterSortProps = {}) {
const storeStatusFilter = useBridgeFilterSortStore((s) => s.statusFilter);
const storeSortBy = useBridgeFilterSortStore((s) => s.sortBy);
const setStatusFilter = useBridgeFilterSortStore((s) => s.setStatusFilter);
const setSortBy = useBridgeFilterSortStore((s) => s.setSortBy);

const statusFilter = statusFilterProp ?? storeStatusFilter;
const sortBy = sortByProp ?? storeSortBy;

const handleStatusChange = (value: string) => {
if (onStatusFilterChange) {
onStatusFilterChange(value);
} else {
setStatusFilter(value as BridgeStatusFilter);
}
};

const handleSortChange = (value: string) => {
if (onSortByChange) {
onSortByChange(value);
} else {
setSortBy(value as BridgeSortBy);
}
};

return (
<div className="flex flex-wrap gap-4 items-center">
<div className="flex items-center gap-2">
Expand All @@ -20,7 +57,7 @@ export default function BridgeFilterSort({
<select
id="status-filter"
value={statusFilter}
onChange={(e) => onStatusFilterChange(e.target.value)}
onChange={(e) => handleStatusChange(e.target.value)}
className="bg-stellar-card border border-stellar-border rounded px-3 py-1.5 text-sm text-stellar-text-primary focus:outline-none focus:ring-2 focus:ring-stellar-blue"
>
<option value="all">All</option>
Expand All @@ -38,7 +75,7 @@ export default function BridgeFilterSort({
<select
id="sort-by"
value={sortBy}
onChange={(e) => onSortByChange(e.target.value)}
onChange={(e) => handleSortChange(e.target.value)}
className="bg-stellar-card border border-stellar-border rounded px-3 py-1.5 text-sm text-stellar-text-primary focus:outline-none focus:ring-2 focus:ring-stellar-blue"
>
<option value="name">Name</option>
Expand Down
10 changes: 7 additions & 3 deletions src/hooks/useWatchlist.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { renderHook, act } from "@testing-library/react";
import { describe, it, expect, beforeEach, beforeAll, afterAll, afterEach } from "vitest";
import { setupServer } from "msw/node";
import { useWatchlist, WatchlistProvider } from "./useWatchlist";
import { useWatchlistStore, WATCHLIST_STORAGE_KEY } from "../stores/watchlistStore";
import React from "react";

// Mock MSW server setup to fulfill established frontend testing patterns,
Expand All @@ -15,6 +16,7 @@ afterEach(() => server.resetHandlers());
describe("useWatchlist", () => {
beforeEach(() => {
window.localStorage.clear();
useWatchlistStore.setState(useWatchlistStore.getInitialState(), true);
});

const wrapper = ({ children }: { children: React.ReactNode }) => (
Expand Down Expand Up @@ -70,11 +72,13 @@ describe("useWatchlist", () => {
result.current.addAsset("BTC");
});

const storedRaw = window.localStorage.getItem("swipely.watchlists.v1");
const storedRaw = window.localStorage.getItem(WATCHLIST_STORAGE_KEY);
expect(storedRaw).toBeTruthy();

const stored = JSON.parse(storedRaw!);
expect(stored.lists[0].assets).toContain("BTC");
// Zustand persist wraps partialized state under `state`.
const lists = stored.state?.lists ?? stored.lists;
expect(lists[0].assets).toContain("BTC");
});

it("should reorder assets", () => {
Expand Down
Loading
Loading