feat: filter regions
This commit is contained in:
15
src/components/button-filter.tsx
Normal file
15
src/components/button-filter.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
export function FilterButton({ children, onClick, active }: { children: ReactNode, onClick?: () => Promise<void> | void, active?: boolean }) {
|
||||
return <div
|
||||
className={classNames("rounded-full outline outline-1 px-4 py-1 cursor-pointer select-none",
|
||||
{
|
||||
"bg-neutral-800 outline-neutral-300": active,
|
||||
"bg-neutral-900 outline-neutral-800 text-neutral-500": !active
|
||||
}
|
||||
)}
|
||||
onClick={onClick}>
|
||||
{children}
|
||||
</div>
|
||||
}
|
@ -1,17 +1,30 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { LNVpsApi, VmTemplateResponse } from "../api";
|
||||
import { LNVpsApi, VmHostRegion, VmTemplateResponse } from "../api";
|
||||
import VpsCard from "../components/vps-card";
|
||||
import { ApiUrl, NostrProfile } from "../const";
|
||||
import { Link } from "react-router-dom";
|
||||
import { VpsCustomOrder } from "../components/vps-custom";
|
||||
import { LatestNews } from "../components/latest-news";
|
||||
import { FilterButton } from "../components/button-filter";
|
||||
import { dedupe } from "@snort/shared";
|
||||
|
||||
export default function HomePage() {
|
||||
const [offers, setOffers] = useState<VmTemplateResponse>();
|
||||
const [region, setRegion] = useState<Array<number>>([]);
|
||||
|
||||
const regions = (offers?.templates.map((t) => t.region) ?? []).reduce((acc, v) => {
|
||||
if (acc[v.id] === undefined) {
|
||||
acc[v.id] = v;
|
||||
}
|
||||
return acc;
|
||||
}, {} as Record<number, VmHostRegion>);
|
||||
|
||||
useEffect(() => {
|
||||
const api = new LNVpsApi(ApiUrl, undefined);
|
||||
api.listOffers().then((o) => setOffers(o));
|
||||
api.listOffers().then((o) => {
|
||||
setOffers(o)
|
||||
setRegion(dedupe(o.templates.map((z) => z.region.id)));
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@ -23,8 +36,24 @@ export default function HomePage() {
|
||||
Virtual Private Server hosting with flexible plans, high uptime, and
|
||||
dedicated support, tailored to your needs.
|
||||
</div>
|
||||
{Object.keys(regions).length > 1 && <div className="flex gap-2 items-center">
|
||||
Regions:
|
||||
{Object.values(regions).map((r) => {
|
||||
return <FilterButton
|
||||
active={region.includes(r.id)}
|
||||
onClick={() => setRegion(x => {
|
||||
if (x.includes(r.id)) {
|
||||
return x.filter(y => y != r.id);
|
||||
} else {
|
||||
return [...x, r.id];
|
||||
}
|
||||
})}>
|
||||
{r.name}
|
||||
</FilterButton>;
|
||||
})}
|
||||
</div>}
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{offers?.templates.map((a) => <VpsCard spec={a} key={a.id} />)}
|
||||
{offers?.templates.filter((t) => region.includes(t.region.id)).sort((a, b) => a.cost_plan.amount - b.cost_plan.amount).map((a) => <VpsCard spec={a} key={a.id} />)}
|
||||
{offers?.templates !== undefined && offers.templates.length === 0 && (
|
||||
<div className="text-red-500 bold text-xl uppercase">
|
||||
No offers available
|
||||
|
Reference in New Issue
Block a user