refactor: property show site list
This commit is contained in:
parent
0aadf6f6f7
commit
7251656bef
|
@ -25,10 +25,11 @@ import {
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "./ui/select";
|
} from "./ui/select";
|
||||||
import { SitesCombobox } from "./SitesCombobox";
|
import { SitesCombobox } from "./SitesCombobox";
|
||||||
|
import { SearchResult, SiteList } from "@/types.js";
|
||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
|
|
||||||
const SearchBar = () => {
|
const SearchBar = ({ sites }: { sites: SiteList }) => {
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
let { pathname } = useLocation();
|
let { pathname } = useLocation();
|
||||||
let [searchParams] = useSearchParams();
|
let [searchParams] = useSearchParams();
|
||||||
|
@ -149,7 +150,7 @@ const SearchBar = () => {
|
||||||
) : (
|
) : (
|
||||||
<div className="justify-self-end min-w-[220px] flex justify-end gap-2">
|
<div className="justify-self-end min-w-[220px] flex justify-end gap-2">
|
||||||
{/* Dropdown component should be here */}
|
{/* Dropdown component should be here */}
|
||||||
<SitesCombobox />
|
<SitesCombobox siteList={sites} />
|
||||||
{/* Dropdown component should be here */}
|
{/* Dropdown component should be here */}
|
||||||
<Select defaultValue={"0"}>
|
<Select defaultValue={"0"}>
|
||||||
<SelectTrigger className="hover:bg-muted w-auto">
|
<SelectTrigger className="hover:bg-muted w-auto">
|
||||||
|
|
|
@ -16,13 +16,20 @@ import {
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { ChevronDownIcon } from "@heroicons/react/24/solid";
|
import { ChevronDownIcon } from "@heroicons/react/24/solid";
|
||||||
import { getAvailableSites } from "@/utils";
|
import { getAvailableSites } from "@/utils";
|
||||||
import { SelectOptions } from "@/types.js";
|
import { SelectOptions, SiteList } from "@/types.js";
|
||||||
|
import slugify from "slugify";
|
||||||
|
|
||||||
export function SitesCombobox() {
|
export function SitesCombobox({ siteList }: { siteList: SiteList }) {
|
||||||
const statuses = getAvailableSites();
|
const sites = Object.entries(siteList).map((item) => {
|
||||||
|
return {
|
||||||
|
label: item[1].name,
|
||||||
|
value: slugify(item[0]),
|
||||||
|
};
|
||||||
|
});
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const [selectedStatus, setSelectedStatus] =
|
const [selectedSite, setSelectedSite] = React.useState<SelectOptions | null>(
|
||||||
React.useState<SelectOptions | null>(null);
|
null
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex- items-center space-x-4">
|
<div className="flex flex- items-center space-x-4">
|
||||||
|
@ -32,24 +39,24 @@ export function SitesCombobox() {
|
||||||
variant={"ghost"}
|
variant={"ghost"}
|
||||||
className="max-w-[120px] focus:ring-2 focus:ring-ring px-2 font-bold items-center w-full flex justify-between text-white text-xs uppercase"
|
className="max-w-[120px] focus:ring-2 focus:ring-ring px-2 font-bold items-center w-full flex justify-between text-white text-xs uppercase"
|
||||||
>
|
>
|
||||||
{selectedStatus ? <>{selectedStatus.label}</> : <>All Sites</>}
|
{selectedSite ? <>{selectedSite.label}</> : <>All Sites</>}
|
||||||
<ChevronDownIcon className="ml-3 w-5 h-5" />
|
<ChevronDownIcon className="ml-3 w-5 h-5" />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="p-0" side="right" align="start">
|
<PopoverContent className="p-0" side="right" align="start">
|
||||||
<Command>
|
<Command>
|
||||||
<CommandInput placeholder="Change status..." />
|
<CommandInput placeholder="Select site..." />
|
||||||
<CommandList>
|
<CommandList>
|
||||||
<CommandEmpty>No results found.</CommandEmpty>
|
<CommandEmpty>No results found.</CommandEmpty>
|
||||||
<CommandGroup>
|
<CommandGroup>
|
||||||
{statuses?.map((status) => (
|
{sites?.map((status) => (
|
||||||
<CommandItem
|
<CommandItem
|
||||||
className="text-white"
|
className="text-white"
|
||||||
key={status.value}
|
key={status.value}
|
||||||
value={status.value}
|
value={status.value}
|
||||||
onSelect={(value) => {
|
onSelect={(value) => {
|
||||||
setSelectedStatus(
|
setSelectedSite(
|
||||||
statuses.find((priority) => priority.value === value) ||
|
sites.find((priority) => priority.value === value) ||
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
|
|
@ -8,9 +8,12 @@ import { Article } from "@/lib/prisma";
|
||||||
import Logo from "@/images/lume-logo-bg.png";
|
import Logo from "@/images/lume-logo-bg.png";
|
||||||
import { json, LoaderFunction, redirect } from "@remix-run/node";
|
import { json, LoaderFunction, redirect } from "@remix-run/node";
|
||||||
import { useLoaderData } from "@remix-run/react";
|
import { useLoaderData } from "@remix-run/react";
|
||||||
|
import type { SiteList } from "@/types.js";
|
||||||
|
import { getAvailableSites } from "@/utils";
|
||||||
|
|
||||||
type LoaderData = {
|
type LoaderData = {
|
||||||
data: ApiResponse<Article>;
|
data: ApiResponse<Article>;
|
||||||
|
sites: SiteList;
|
||||||
};
|
};
|
||||||
|
|
||||||
export let loader: LoaderFunction = async ({ request }) => {
|
export let loader: LoaderFunction = async ({ request }) => {
|
||||||
|
@ -26,15 +29,17 @@ export let loader: LoaderFunction = async ({ request }) => {
|
||||||
// Fetch your data here
|
// Fetch your data here
|
||||||
const data = await fetchFeedData({});
|
const data = await fetchFeedData({});
|
||||||
|
|
||||||
|
const sites = getAvailableSites();
|
||||||
|
|
||||||
// Return the fetched data as JSON
|
// Return the fetched data as JSON
|
||||||
return json({ data });
|
return json({ data, sites });
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
let { data } = useLoaderData<LoaderData>();
|
let { data, sites } = useLoaderData<LoaderData>();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SearchBar />
|
<SearchBar sites={sites} />
|
||||||
<div className="space-y-8 w-full my-10">
|
<div className="space-y-8 w-full my-10">
|
||||||
<div className="flex flex-row flex-wrap justify-between w-full">
|
<div className="flex flex-row flex-wrap justify-between w-full">
|
||||||
<Feed
|
<Feed
|
||||||
|
|
|
@ -10,3 +10,10 @@ export type SelectOptions = {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SiteList = {
|
||||||
|
[domain: string]: {
|
||||||
|
name: string;
|
||||||
|
pubkey: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
32
app/utils.ts
32
app/utils.ts
|
@ -1,7 +1,8 @@
|
||||||
import { formatDistanceToNow, subDays, subMonths, subYears } from "date-fns";
|
import { formatDistanceToNow, subDays, subMonths, subYears } from "date-fns";
|
||||||
import { clsx, type ClassValue } from "clsx";
|
import { type ClassValue, clsx } from "clsx";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import { SearchResult, SelectOptions } from "@/types.js";
|
import { SearchResult, SiteList } from "@/types.js";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
|
@ -45,30 +46,9 @@ export async function getResults({
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAvailableSites() {
|
export function getAvailableSites() {
|
||||||
const statuses: SelectOptions[] = [
|
return JSON.parse(
|
||||||
{
|
fs.readFileSync("sites.json", { encoding: "utf8" })
|
||||||
value: "backlog",
|
) as SiteList;
|
||||||
label: "Backlog",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "todo",
|
|
||||||
label: "Todo",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "in progress",
|
|
||||||
label: "In Progress",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "done",
|
|
||||||
label: "Done",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "canceled",
|
|
||||||
label: "Canceled",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return statuses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FILTER_TIMES = [
|
export const FILTER_TIMES = [
|
||||||
|
|
12
bridge.mts
12
bridge.mts
|
@ -1,17 +1,9 @@
|
||||||
import * as fs from "fs";
|
|
||||||
import { S5Client } from "@lumeweb/s5-js";
|
import { S5Client } from "@lumeweb/s5-js";
|
||||||
import { CID } from "@lumeweb/libs5";
|
import { CID } from "@lumeweb/libs5";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { getAvailableSites } from "app/utils.js";
|
||||||
|
|
||||||
type SiteList = {
|
const sites = getAvailableSites();
|
||||||
[domain: string]: {
|
|
||||||
pubkey: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const sites = JSON.parse(
|
|
||||||
fs.readFileSync("sites.json", { encoding: "utf8" }),
|
|
||||||
) as SiteList;
|
|
||||||
|
|
||||||
const client = new S5Client("https://s5.web3portal.com");
|
const client = new S5Client("https://s5.web3portal.com");
|
||||||
const httpClient = axios.create({
|
const httpClient = axios.create({
|
||||||
|
|
Loading…
Reference in New Issue