Skip to content

Commit

Permalink
chore(Search): externalize HomeSearch component
Browse files Browse the repository at this point in the history
  • Loading branch information
mjkeaton committed Jan 7, 2025
1 parent 84235ae commit 31a701a
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 112 deletions.
119 changes: 119 additions & 0 deletions src/pages/home/HomeSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { FormattedMessage, } from "react-intl";

import Icon from "../contacts/components/Icon";
import { type Contact, ContactTypes } from "@/types/contact";
import { randomAvatar } from "@/utils/dev";
import { SearchIcon } from "lucide-react";
import { Skeleton } from "@/components/ui/skeleton";


type RecentContactItemProps = Pick<Contact, "name" | "type" | "avatar">;

function RecentContactItem({ name, type, avatar }: RecentContactItemProps) {
return (
<div className="flex flex-col items-center gap-1 w-14">
<Icon name={name} type={type} avatar={avatar} className="w-8 h-8" />
<div className="text-text-300 text-[11px] font-medium text-center">{name}</div>
</div>
);
}

function RecentContacts({ values }: { values: RecentContactItemProps[] }) {
return (
<div className="flex flex-col gap-2 w-full">
<div className="text-text-200 text-xs font-medium">
<FormattedMessage
id="Recent"
defaultMessage="Recent"
description="Title for recent contacts on home page"
/>
</div>
<div className="flex gap-4">
{values.map((value, index) => (
<RecentContactItem key={index} {...value} />
))}
</div>
</div>
);
}

function SearchSuggestions() {
return (
<div className="flex flex-col gap-4 w-full">
<div className="text-text-200 text-xs font-medium">
<FormattedMessage
id="Try searching for"
defaultMessage="Try searching for"
description="Title for search suggestions on home page"
/>
</div>
<div className="flex flex-col gap-6 text-text-300 text-sm font-medium">
<div className="flex items-center gap-2">
<SearchIcon className="w-5 h-5" strokeWidth={1} />
<FormattedMessage
id="Recent bills"
defaultMessage="Recent bills"
description="Search suggestion for recent bills on home page"
/>
</div>
<div className="flex items-center gap-2">
<SearchIcon className="w-5 h-5" strokeWidth={1} />
<FormattedMessage
id="All contacts"
defaultMessage="All contacts"
description="Search suggestion for all contacts on home page"
/>
</div>
<div className="flex items-center gap-2">
<SearchIcon className="w-5 h-5" strokeWidth={1} />
Something here
</div>
</div>
</div>
);
}

function SearchResults() {
return (
<div className="flex flex-col gap-4 w-full">
<div className="text-text-200 text-xs font-medium">
<FormattedMessage
id="Search results"
defaultMessage="Search results"
description="Title for search results on home page"
/>
</div>
<div className="flex items-center gap-2 text-text-300 text-sm font-medium">
</div>
</div>
);
}

function Loader() {
return (
<div className="flex flex-col gap-3 w-full">
{Array.from({ length: 3 }, (_, index) => (
<Skeleton key={index} className="w-full h-14 bg-elevation-200 rounded-sm" />
))}
</div>
);
}

const __dev__RECENT_CONTACTS = [
{ name: "Matt Preziegka", type: ContactTypes.Person, avatar: randomAvatar("men") },
{ name: "Jurica Kolectic", type: ContactTypes.Person, avatar: randomAvatar("men") },
{ name: "Testla Inc", type: ContactTypes.Company },
{ name: "Mia Flores", type: ContactTypes.Person, avatar: randomAvatar("women") },
];

export default function HomeSearch({ isPending }: { isPending: boolean }) {

return (
<div className="flex flex-col gap-6 mt-2 w-full">
<RecentContacts values={__dev__RECENT_CONTACTS} />
<SearchSuggestions />
<SearchResults />
{isPending && <Loader />}
</div>
);
}
132 changes: 20 additions & 112 deletions src/pages/home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,121 +1,32 @@
import { FormattedMessage, useIntl } from "react-intl";
import Topbar from "@/components/Topbar";
import Search from "@/components/ui/search";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { useState } from "react";
import { useIntl } from "react-intl";
import { ChevronLeftIcon } from "lucide-react";

import Balances from "./components/Balances";
import Bills from "./components/Bills";
import { useQuery } from "@tanstack/react-query";
import { search } from "@/services/search";
import { useState } from "react";
import { cn } from "@/lib/utils";

import SearchTypeFilter, { type SearchTypeFilterValue } from "./components/SearchTypeFilter";
import { cn } from "@/lib/utils";
import Topbar from "@/components/Topbar";
import Search from "@/components/ui/search";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { ChevronLeftIcon, SearchIcon } from "lucide-react";
import { Separator } from "@/components/ui/separator";
import Icon from "../contacts/components/Icon";
import { type Contact, ContactTypes } from "@/types/contact";
import { randomAvatar } from "@/utils/dev";


type RecentContactItemProps = Pick<Contact, "name" | "type" | "avatar">;
function RecentContactItem({ name, type, avatar }: RecentContactItemProps) {
return (
<div className="flex flex-col items-center gap-1 w-14">
<Icon name={name} type={type} avatar={avatar} className="w-8 h-8" />
<div className="text-text-300 text-[11px] font-medium text-center">{name}</div>
</div>
);
}

function RecentContacts({ values }: { values: RecentContactItemProps[] }) {
return (
<div className="flex flex-col gap-2 w-full">
<div className="text-text-200 text-xs font-medium">
<FormattedMessage
id="Recent"
defaultMessage="Recent"
description="Title for recent contacts on home page"
/>
</div>
<div className="flex gap-4">
{values.map((value) => (
<RecentContactItem key={value.name} {...value} />
))}
</div>
</div>
);
}

function SearchSuggestions() {
return (
<div className="flex flex-col gap-4 w-full">
<div className="text-text-200 text-xs font-medium">
<FormattedMessage
id="Try searching for"
defaultMessage="Try searching for"
description="Title for search suggestions on home page"
/>
</div>
<div className="flex flex-col gap-6 text-text-300 text-sm font-medium">
<div className="flex items-center gap-2">
<SearchIcon className="w-5 h-5" strokeWidth={1} />
<FormattedMessage
id="Recent bills"
defaultMessage="Recent bills"
description="Search suggestion for recent bills on home page"
/>
</div>
<div className="flex items-center gap-2">
<SearchIcon className="w-5 h-5" strokeWidth={1} />
<FormattedMessage
id="All contacts"
defaultMessage="All contacts"
description="Search suggestion for all contacts on home page"
/>
</div>
<div className="flex items-center gap-2">
<SearchIcon className="w-5 h-5" strokeWidth={1} />
Something here
</div>
</div>
</div>
);
}

function SearchResults() {
return (
<div className="flex flex-col gap-4 w-full">
<div className="text-text-200 text-xs font-medium">
<FormattedMessage
id="Search results"
defaultMessage="Search results"
description="Title for search results on home page"
/>
</div>
<div className="flex items-center gap-2 text-text-300 text-sm font-medium">
</div>
</div>
);
}

const __dev__RECENT_CONTACTS = [
{ name: "Matt Preziegka", type: ContactTypes.Person, avatar: randomAvatar("men") },
{ name: "Jurica Kolectic", type: ContactTypes.Person, avatar: randomAvatar("men") },
{ name: "Testla Inc", type: ContactTypes.Company },
{ name: "Mia Flores", type: ContactTypes.Person, avatar: randomAvatar("women") },
];
import Balances from "./components/Balances";
import Bills from "./components/Bills";
import SearchTypeFilter, { type SearchTypeFilterValue } from "./components/SearchTypeFilter";
import HomeSearch from "./HomeSearch";

export default function Home() {
const intl = useIntl();

const [typeFilters, setTypeFilters] = useState<SearchTypeFilterValue[]>(["all"]);
const [searchTerm, setSearchTerm] = useState("");
const [typeFilters, setTypeFilters] = useState<SearchTypeFilterValue[]>(["all"]);

const [searchModeEnabled, setSearchModeEnabled] = useState(searchTerm.length > 0);

const { isPending, isSuccess, data } = useQuery({
queryKey: ["search"],
queryKey: ["search", searchTerm, typeFilters],
queryFn: () => search({
filter: {
search_term: searchTerm,
Expand Down Expand Up @@ -175,18 +86,15 @@ export default function Home() {
<div className={cn("flex flex-col gap-2", "transition-opacity duration-200 ease-in-out", {
"opacity-0 pointer-events-none": !searchModeEnabled,
})}>
<div className="flex flex-col gap-2">
<SearchTypeFilter multiple values={typeFilters} onChange={setTypeFilters} />
<Separator className="bg-divider-75" />

<div className="flex flex-col gap-6 mt-2 w-full">
<RecentContacts values={__dev__RECENT_CONTACTS} />
<SearchSuggestions />
<SearchResults />
</div>
</div>
<div className="flex flex-col gap-2">
<SearchTypeFilter multiple values={typeFilters} onChange={setTypeFilters} />
<Separator className="bg-divider-75" />

<HomeSearch isPending={isPending} />
</div>

</div>
</div>
);
}

0 comments on commit 31a701a

Please sign in to comment.