Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter performance and UI touchups #81

Merged
merged 14 commits into from
Apr 4, 2024
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
10 changes: 5 additions & 5 deletions components/report-details/report-support-feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ const MobileFeed = ({ contributions }: { contributions: Contribution[] }) => {
const DesktopFeed = ({ contributions }: { contributions: Contribution[] }) => {
return (
<ol
className="border-l border-neutral-300 dark:border-neutral-500 hidden md:block"
className="border-l border-stone-300 dark:border-stone-500 hidden md:block"
aria-label="Contributions list"
>
{contributions.map((contribution) => (
Expand All @@ -182,7 +182,7 @@ const DesktopFeed = ({ contributions }: { contributions: Contribution[] }) => {
aria-labelledby="contributor-info"
>
<span
className="-ml-[5px] mr-3 h-[9px] w-[9px] rounded-full bg-neutral-300 dark:bg-neutral-500"
className="-ml-[5px] mr-3 h-[9px] w-[9px] rounded-full bg-stone-300 dark:bg-stone-500"
aria-hidden="true"
/>
<div className="flex items-center gap-2" id="contributor-info">
Expand All @@ -202,7 +202,7 @@ const DesktopFeed = ({ contributions }: { contributions: Contribution[] }) => {
)}
<DotIcon className="text-stone-400" aria-hidden="true" />
<p
className="text-sm text-neutral-500 dark:text-neutral-300"
className="text-sm text-stone-500 dark:text-stone-300"
aria-label={`Contribution date: ${transformDate(
contribution.date_created,
)}`}
Expand All @@ -214,7 +214,7 @@ const DesktopFeed = ({ contributions }: { contributions: Contribution[] }) => {
{contribution.comment && (
<div className="mb-6 ml-4 mt-2">
<p
className="mb-3 text-neutral-500 dark:text-neutral-300"
className="mb-3 text-stone-500 dark:text-stone-300"
role="article"
aria-label="Contribution comment"
>
Expand Down Expand Up @@ -251,7 +251,7 @@ const ReportSupportFeed = ({
<h3 className="text-2xl font-semibold py-4" id="support-feed-title">
Support Feed
</h3>
<p className="text-neutral-500 dark:text-neutral-300">
<p className="text-stone-500 dark:text-stone-300">
Nothing to show yet. Be the first to support this cause!
</p>
</section>
Expand Down
2 changes: 1 addition & 1 deletion components/reports/reports-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export const FilterItems: React.FC<FilterItemsProps> = ({
{uniqueCategories.map(({ label, value }) => (
<Badge
key={value}
className={`border-vd-blue-500 rounded-full flex flex-auto flex-col md:flex-row items-center gap-1 px-2 py-1 cursor-pointer ${
className={`border-vd-blue-500 rounded-2xl flex flex-auto flex-col items-center gap-1 px-2 py-3 cursor-pointer ${
selectedCategory === value
? "bg-vd-blue-900 text-vd-beige-100 hover:bg-vd-blue-700"
: ""
Expand Down
14 changes: 6 additions & 8 deletions hooks/use-buy-fraction.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { useGetCurrentERC20Allowance } from "@/hooks/use-get-current-erc20-allowance";
import type { HypercertExchangeClient } from "@hypercerts-org/marketplace-sdk";
import { useState } from "react";
import type { Address } from "viem";
import { waitForTransactionReceipt } from "viem/actions";
import type { UsePublicClientReturnType } from "wagmi";

export enum TransactionStatuses {
PreparingOrder = "preparingOrder",
Approval = "approval",
SignForBuy = "signForBuy",
Pending = "pending",
Confirmed = "confirmed",
Failed = "failed",
PreparingOrder = 0,
Approval = 1,
SignForBuy = 2,
Pending = 3,
Confirmed = 4,
Failed = 5,
}

const useHandleBuyFraction = (
Expand All @@ -21,7 +20,6 @@ const useHandleBuyFraction = (
const [transactionStatus, setTransactionStatus] =
useState<keyof typeof TransactionStatuses>("Pending");
const [transactionHash, setTransactionHash] = useState<Address | null>(null);
const currentAllowance = useGetCurrentERC20Allowance();

const handleBuyFraction = async (
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
Expand Down
150 changes: 79 additions & 71 deletions lib/search-filter-utils.ts
Original file line number Diff line number Diff line change
@@ -1,90 +1,98 @@
import type { ISortingOption, Report } from "@/types";
import type Fuse from "fuse.js";

export const filterReports = (
reports: Report[],
filters: [string, string][],
fuse: Fuse<Report>
) => {
return filters.reduce((filteredReports, [key, value]) => {
switch (key) {
case "q": {
const searchResults = fuse.search(value);
return searchResults.map((result) => result.item);
}
case "state": {
const states = filters
.filter(([filterKey]) => filterKey === "state")
.map(([, filterValue]) => filterValue);
return filteredReports.filter((report) =>
states.includes(report.state)
);
}
case "min":
return filteredReports.filter(
(report) =>
report.totalCost - report.fundedSoFar >= Number.parseInt(value, 10)
);
case "max":
return filteredReports.filter(
(report) =>
report.totalCost - report.fundedSoFar <= Number.parseInt(value, 10)
);
case "category":
return filteredReports.filter((report) => report.category === value);
case "outlet": {
const outlets = filters
.filter(([filterKey]) => filterKey === "outlet")
.map(([, filterValue]) =>
decodeURIComponent(filterValue).toLowerCase()
);
return filteredReports.filter((report) => {
if (!report.contributors.length) return false;
const outletName = report.contributors[0].toLowerCase();
return outlets.includes(outletName);
});
}
default:
return filteredReports;
// search first
let searchedReports = reports;
const searchQuery = filters.find(([filterKey]) => filterKey === "q")?.[1];
if (searchQuery) {
const searchResults = fuse.search(searchQuery);
searchedReports = searchResults.map((result) => result.item);
}

// pre-process filters
const statesSet = new Set(
filters
.filter(([filterKey]) => filterKey === "state")
.map(([, filterValue]) => filterValue)
);
const outletsSet = new Set(
filters
.filter(([filterKey]) => filterKey === "outlet")
.map(([, filterValue]) => decodeURIComponent(filterValue).toLowerCase())
);

const minAmountFromFilter = filters.find(
([filterKey]) => filterKey === "min"
)?.[1];
const maxAmountFromFilter = filters.find(
([filterKey]) => filterKey === "max"
)?.[1];
const minAmount = minAmountFromFilter
? Number.parseInt(minAmountFromFilter, 10)
: null;
const maxAmount = maxAmountFromFilter
? Number.parseInt(maxAmountFromFilter, 10)
: null;

return searchedReports.filter((report) => {
const remainingCost = report.totalCost - report.fundedSoFar;
// check state filter
if (statesSet.size > 0 && !statesSet.has(report.state)) return false;
// check outlet filter
if (outletsSet.size > 0 && report.contributors.length) {
const outletName = report.contributors[0].toLowerCase();
if (!outletName || !outletsSet.has(outletName)) return false;
}
// check category
if (
filters.some(
([key, value]) => key === "category" && report.category !== value
)
) {
return false;
}
}, reports);

// check min and max amount filter
if (minAmount !== null && remainingCost < minAmount) return false;
if (maxAmount !== null && remainingCost > maxAmount) return false;

return true;
});
};

export const createFilterOptions = (reports: Report[]) => {
const uniqueCategories = reports
.map((report: Report, index: number) => ({
const uniqueCategoriesMap = new Map();
const uniqueOutletsMap = new Map();
const uniqueStatesMap = new Map();
const amountsNeeded = [];

for (let i = 0; i < reports.length; i++) {
const report = reports[i];
uniqueCategoriesMap.set(report.category, {
label: report.category,
value: report.category,
}))
.filter(
({ value }, index, self) =>
index === self.findIndex((obj) => obj.value === value)
);

const uniqueOutlets = reports
.map((report: Report) => report.contributors[0])
.filter((outlet) => outlet && outlet.length > 0)
.map((outlet: string) => ({
label: outlet,
value: encodeURIComponent(outlet).toLowerCase(),
}))
.filter(
({ value }, index, self) =>
index === self.findIndex((obj) => obj.value === value)
);

const uniqueStates = reports
.map((report: Report, index: number) => ({
});
if (report.contributors[0] && report.contributors[0].length > 0) {
uniqueOutletsMap.set(report.contributors[0].toLowerCase(), {
label: report.contributors[0],
value: encodeURIComponent(report.contributors[0]).toLowerCase(),
});
}
uniqueStatesMap.set(report.state, {
label: report.state,
value: report.state,
}))
.filter(
({ value }, index, self) =>
index === self.findIndex((obj) => obj.value === value)
);
});
amountsNeeded.push(report.totalCost - report.fundedSoFar || 0);
}

const amountsNeeded = reports.map(
(report: Report) => report.totalCost - report.fundedSoFar || 0
);
const uniqueCategories = Array.from(uniqueCategoriesMap.values());
const uniqueOutlets = Array.from(uniqueOutletsMap.values());
const uniqueStates = Array.from(uniqueStatesMap.values());
const minAmountNeeded = Math.min(...amountsNeeded);
const maxAmountNeeded = Math.max(...amountsNeeded);

Expand Down
Loading