repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | import { useState, useEffect } from "react"; |
| #2 | import { Button } from "@/components/ui/button"; |
| #3 | import { Category, Client } from "../../../components/types"; |
| #4 | import { MemoryTable } from "./MemoryTable"; |
| #5 | import { MemoryPagination } from "./MemoryPagination"; |
| #6 | import { CreateMemoryDialog } from "./CreateMemoryDialog"; |
| #7 | import { PageSizeSelector } from "./PageSizeSelector"; |
| #8 | import { useMemoriesApi } from "@/hooks/useMemoriesApi"; |
| #9 | import { useRouter, useSearchParams } from "next/navigation"; |
| #10 | import { MemoryTableSkeleton } from "@/skeleton/MemoryTableSkeleton"; |
| #11 | |
| #12 | export function MemoriesSection() { |
| #13 | const router = useRouter(); |
| #14 | const searchParams = useSearchParams(); |
| #15 | const { fetchMemories } = useMemoriesApi(); |
| #16 | const [memories, setMemories] = useState<any[]>([]); |
| #17 | const [totalItems, setTotalItems] = useState(0); |
| #18 | const [totalPages, setTotalPages] = useState(1); |
| #19 | const [isLoading, setIsLoading] = useState(true); |
| #20 | |
| #21 | const currentPage = Number(searchParams.get("page")) || 1; |
| #22 | const itemsPerPage = Number(searchParams.get("size")) || 10; |
| #23 | const [selectedCategory, setSelectedCategory] = useState<Category | "all">( |
| #24 | "all" |
| #25 | ); |
| #26 | const [selectedClient, setSelectedClient] = useState<Client | "all">("all"); |
| #27 | |
| #28 | useEffect(() => { |
| #29 | const loadMemories = async () => { |
| #30 | setIsLoading(true); |
| #31 | try { |
| #32 | const searchQuery = searchParams.get("search") || ""; |
| #33 | const result = await fetchMemories( |
| #34 | searchQuery, |
| #35 | currentPage, |
| #36 | itemsPerPage |
| #37 | ); |
| #38 | setMemories(result.memories); |
| #39 | setTotalItems(result.total); |
| #40 | setTotalPages(result.pages); |
| #41 | } catch (error) { |
| #42 | console.error("Failed to fetch memories:", error); |
| #43 | } |
| #44 | setIsLoading(false); |
| #45 | }; |
| #46 | |
| #47 | loadMemories(); |
| #48 | }, [currentPage, itemsPerPage, fetchMemories, searchParams]); |
| #49 | |
| #50 | const setCurrentPage = (page: number) => { |
| #51 | const params = new URLSearchParams(searchParams.toString()); |
| #52 | params.set("page", page.toString()); |
| #53 | params.set("size", itemsPerPage.toString()); |
| #54 | router.push(`?${params.toString()}`); |
| #55 | }; |
| #56 | |
| #57 | const handlePageSizeChange = (size: number) => { |
| #58 | const params = new URLSearchParams(searchParams.toString()); |
| #59 | params.set("page", "1"); // Reset to page 1 when changing page size |
| #60 | params.set("size", size.toString()); |
| #61 | router.push(`?${params.toString()}`); |
| #62 | }; |
| #63 | |
| #64 | if (isLoading) { |
| #65 | return ( |
| #66 | <div className="w-full bg-transparent"> |
| #67 | <MemoryTableSkeleton /> |
| #68 | <div className="flex items-center justify-between mt-4"> |
| #69 | <div className="h-8 w-32 bg-zinc-800 rounded animate-pulse" /> |
| #70 | <div className="h-8 w-48 bg-zinc-800 rounded animate-pulse" /> |
| #71 | <div className="h-8 w-32 bg-zinc-800 rounded animate-pulse" /> |
| #72 | </div> |
| #73 | </div> |
| #74 | ); |
| #75 | } |
| #76 | |
| #77 | return ( |
| #78 | <div className="w-full bg-transparent"> |
| #79 | <div> |
| #80 | {memories.length > 0 ? ( |
| #81 | <> |
| #82 | <MemoryTable /> |
| #83 | <div className="flex items-center justify-between mt-4"> |
| #84 | <PageSizeSelector |
| #85 | pageSize={itemsPerPage} |
| #86 | onPageSizeChange={handlePageSizeChange} |
| #87 | /> |
| #88 | <div className="text-sm text-zinc-500 mr-2"> |
| #89 | Showing {(currentPage - 1) * itemsPerPage + 1} to{" "} |
| #90 | {Math.min(currentPage * itemsPerPage, totalItems)} of{" "} |
| #91 | {totalItems} memories |
| #92 | </div> |
| #93 | <MemoryPagination |
| #94 | currentPage={currentPage} |
| #95 | totalPages={totalPages} |
| #96 | setCurrentPage={setCurrentPage} |
| #97 | /> |
| #98 | </div> |
| #99 | </> |
| #100 | ) : ( |
| #101 | <div className="flex flex-col items-center justify-center py-12 text-center"> |
| #102 | <div className="rounded-full bg-zinc-800 p-3 mb-4"> |
| #103 | <svg |
| #104 | xmlns="http://www.w3.org/2000/svg" |
| #105 | width="24" |
| #106 | height="24" |
| #107 | viewBox="0 0 24 24" |
| #108 | fill="none" |
| #109 | stroke="currentColor" |
| #110 | strokeWidth="2" |
| #111 | strokeLinecap="round" |
| #112 | strokeLinejoin="round" |
| #113 | className="h-6 w-6 text-zinc-400" |
| #114 | > |
| #115 | <path d="M21 9v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"></path> |
| #116 | <path d="M16 2v6h6"></path> |
| #117 | <path d="M12 18v-6"></path> |
| #118 | <path d="M9 15h6"></path> |
| #119 | </svg> |
| #120 | </div> |
| #121 | <h3 className="text-lg font-medium">No memories found</h3> |
| #122 | <p className="text-zinc-400 mt-1 mb-4"> |
| #123 | {selectedCategory !== "all" || selectedClient !== "all" |
| #124 | ? "Try adjusting your filters" |
| #125 | : "Create your first memory to see it here"} |
| #126 | </p> |
| #127 | {selectedCategory !== "all" || selectedClient !== "all" ? ( |
| #128 | <Button |
| #129 | variant="outline" |
| #130 | onClick={() => { |
| #131 | setSelectedCategory("all"); |
| #132 | setSelectedClient("all"); |
| #133 | }} |
| #134 | > |
| #135 | Clear Filters |
| #136 | </Button> |
| #137 | ) : ( |
| #138 | <CreateMemoryDialog /> |
| #139 | )} |
| #140 | </div> |
| #141 | )} |
| #142 | </div> |
| #143 | </div> |
| #144 | ); |
| #145 | } |
| #146 |