removed home page. fixed searching. added "/" shortcut to start searching. made it so that the whole accordion fits on screen.
This commit is contained in:
@@ -54,4 +54,12 @@
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-state="open"] .accordioncontent {
|
||||
display: block;
|
||||
}
|
||||
|
||||
[data-state="closed"] .accordioncontent {
|
||||
display: none;
|
||||
}
|
||||
@@ -116,7 +116,7 @@ function Page() {
|
||||
<Dialog key={item.id}>
|
||||
<DialogTrigger asChild>
|
||||
<div
|
||||
className="flex min-w-[400px] max-w-[400px] cursor-pointer flex-col rounded-lg border border-b bg-gray-900 p-4 backdrop-blur-xl"
|
||||
className="flex min-w-[400px] max-w-[400px] animate-fade-up cursor-pointer flex-col rounded-lg border border-b bg-gray-900 p-4 backdrop-blur-xl"
|
||||
onClick={() => setSelectedItem(item.id)}
|
||||
>
|
||||
<div className="flex justify-between">
|
||||
|
||||
146
app/page.tsx
146
app/page.tsx
@@ -1,11 +1,147 @@
|
||||
import LandingPage from "@/components/LandingPage";
|
||||
"use client";
|
||||
import React, { useEffect, useState, useRef } from "react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
AccordionContent,
|
||||
} from "@/components/ui/accordion";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import ScriptItem from "@/components/Script";
|
||||
import { pb } from "@/lib/pocketbase";
|
||||
|
||||
interface Script {
|
||||
title: string;
|
||||
scriptID: string;
|
||||
}
|
||||
|
||||
interface Category {
|
||||
id: string;
|
||||
Catagory_Title: string;
|
||||
Items: Script[];
|
||||
}
|
||||
|
||||
type Scripts = {
|
||||
id: string;
|
||||
title: string;
|
||||
logo: string;
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
const [selectedItem, setSelectedItem] = useState("");
|
||||
const [items, setItems] = useState<Scripts[]>([]);
|
||||
const [links, setLinks] = useState<Category[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [accordionExpanded, setAccordionExpanded] = useState(false);
|
||||
const inputRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: any) => {
|
||||
if (event.key === "/") {
|
||||
inputRef.current.focus();
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const data = await getLinks();
|
||||
const items = await getItems();
|
||||
setLinks(data);
|
||||
setItems(items);
|
||||
} catch (error) {
|
||||
console.error("Error fetching links:", error);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const getLinks = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_POCKETBASE_URL}/api/collections/proxmox_items/records`,
|
||||
);
|
||||
const data = await res.json();
|
||||
return data.items as Category[];
|
||||
};
|
||||
|
||||
const getItems = async () => {
|
||||
const records = await pb.collection("proxmox_scripts").getFullList({
|
||||
sort: "-created",
|
||||
});
|
||||
return records as unknown as Scripts[];
|
||||
};
|
||||
|
||||
const handleSearch = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
setAccordionExpanded(true); // Expand the accordion when searching
|
||||
};
|
||||
|
||||
const filteredLinks = searchTerm
|
||||
? links
|
||||
.map((category) => ({
|
||||
...category,
|
||||
Items: category.Items.filter((script) =>
|
||||
script.title.toLowerCase().includes(searchTerm.toLowerCase()),
|
||||
),
|
||||
}))
|
||||
.filter((category) => category.Items.length > 0)
|
||||
: links;
|
||||
|
||||
function page() {
|
||||
return (
|
||||
<>
|
||||
<LandingPage />
|
||||
<div className="mt-20 flex">
|
||||
<div className="flex min-w-72 max-w-72 flex-col">
|
||||
<h1 className="mb-5 text-xl font-bold">Scripts</h1>
|
||||
<Input
|
||||
className="mb-5"
|
||||
type="text"
|
||||
placeholder="Type '/' to search"
|
||||
value={searchTerm}
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<Accordion
|
||||
type={searchTerm ? "multiple" : "single"}
|
||||
collapsible
|
||||
data-state={accordionExpanded ? "open" : "closed"}
|
||||
className="data-[state=open]"
|
||||
>
|
||||
{filteredLinks.map((category) => (
|
||||
<AccordionItem
|
||||
value={category.id}
|
||||
key={category.id}
|
||||
className={`text-md data-[state=open]: flex flex-col gap-2 `}
|
||||
>
|
||||
<AccordionTrigger>{category.Catagory_Title}</AccordionTrigger>
|
||||
<AccordionContent
|
||||
className={`${accordionExpanded ? "data-[state=closed]" : "data-[state=open"}`}
|
||||
>
|
||||
{category.Items.map((script, index) => (
|
||||
<p
|
||||
className="cursor-pointer text-muted-foreground"
|
||||
onClick={() => setSelectedItem(script.scriptID)}
|
||||
key={index}
|
||||
>
|
||||
{script.title}
|
||||
</p>
|
||||
))}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
))}
|
||||
</Accordion>
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="h-screen w-full">
|
||||
<ScriptItem scriptID={selectedItem} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default page;
|
||||
|
||||
@@ -28,7 +28,7 @@ const AccordionTrigger = React.forwardRef<
|
||||
<AccordionPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
|
||||
"flex flex-1 items-center justify-between py-1 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user