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 Image from "next/image"; |
| #2 | import { useEffect, useState } from "react"; |
| #3 | import { useMemoriesApi } from "@/hooks/useMemoriesApi"; |
| #4 | import { constants } from "@/components/shared/source-app"; |
| #5 | import { useSelector } from "react-redux"; |
| #6 | import { RootState } from "@/store/store"; |
| #7 | import { ScrollArea } from "@/components/ui/scroll-area"; |
| #8 | |
| #9 | interface AccessLogEntry { |
| #10 | id: string; |
| #11 | app_name: string; |
| #12 | accessed_at: string; |
| #13 | } |
| #14 | |
| #15 | interface AccessLogProps { |
| #16 | memoryId: string; |
| #17 | } |
| #18 | |
| #19 | export function AccessLog({ memoryId }: AccessLogProps) { |
| #20 | const { fetchAccessLogs } = useMemoriesApi(); |
| #21 | const accessEntries = useSelector( |
| #22 | (state: RootState) => state.memories.accessLogs |
| #23 | ); |
| #24 | const [isLoading, setIsLoading] = useState(true); |
| #25 | |
| #26 | useEffect(() => { |
| #27 | const loadAccessLogs = async () => { |
| #28 | try { |
| #29 | await fetchAccessLogs(memoryId); |
| #30 | } catch (error) { |
| #31 | console.error("Failed to fetch access logs:", error); |
| #32 | } finally { |
| #33 | setIsLoading(false); |
| #34 | } |
| #35 | }; |
| #36 | |
| #37 | loadAccessLogs(); |
| #38 | }, []); |
| #39 | |
| #40 | if (isLoading) { |
| #41 | return ( |
| #42 | <div className="w-full max-w-md mx-auto rounded-3xl overflow-hidden bg-[#1c1c1c] text-white p-6"> |
| #43 | <p className="text-center text-zinc-500">Loading access logs...</p> |
| #44 | </div> |
| #45 | ); |
| #46 | } |
| #47 | |
| #48 | return ( |
| #49 | <div className="w-full max-w-md mx-auto rounded-lg overflow-hidden bg-zinc-900 border border-zinc-800 text-white pb-1"> |
| #50 | <div className="px-6 py-4 flex justify-between items-center bg-zinc-800 border-b border-zinc-800"> |
| #51 | <h2 className="font-semibold">Access Log</h2> |
| #52 | {/* <button className="px-3 py-1 text-sm rounded-lg border border-[#ff5533] text-[#ff5533] flex items-center gap-2 hover:bg-[#ff5533]/10 transition-colors"> |
| #53 | <PauseIcon size={18} /> |
| #54 | <span>Pause Access</span> |
| #55 | </button> */} |
| #56 | </div> |
| #57 | |
| #58 | <ScrollArea className="p-6 max-h-[450px]"> |
| #59 | {accessEntries.length === 0 && ( |
| #60 | <div className="w-full max-w-md mx-auto rounded-3xl overflow-hidden min-h-[110px] flex items-center justify-center text-white p-6"> |
| #61 | <p className="text-center text-zinc-500"> |
| #62 | No access logs available |
| #63 | </p> |
| #64 | </div> |
| #65 | )} |
| #66 | <ul className="space-y-8"> |
| #67 | {accessEntries.map((entry: AccessLogEntry, index: number) => { |
| #68 | const appConfig = |
| #69 | constants[entry.app_name as keyof typeof constants] || |
| #70 | constants.default; |
| #71 | |
| #72 | return ( |
| #73 | <li key={entry.id} className="relative flex items-start gap-4"> |
| #74 | <div className="relative z-10 rounded-full overflow-hidden bg-[#2a2a2a] w-8 h-8 flex items-center justify-center flex-shrink-0"> |
| #75 | {appConfig.iconImage ? ( |
| #76 | <Image |
| #77 | src={appConfig.iconImage} |
| #78 | alt={`${appConfig.name} icon`} |
| #79 | width={30} |
| #80 | height={30} |
| #81 | className="w-8 h-8 object-contain" |
| #82 | /> |
| #83 | ) : ( |
| #84 | <div className="w-8 h-8 flex items-center justify-center"> |
| #85 | {appConfig.icon} |
| #86 | </div> |
| #87 | )} |
| #88 | </div> |
| #89 | |
| #90 | {index < accessEntries.length - 1 && ( |
| #91 | <div className="absolute left-4 top-6 bottom-0 w-[1px] h-[calc(100%+1rem)] bg-[#333333] transform -translate-x-1/2"></div> |
| #92 | )} |
| #93 | |
| #94 | <div className="flex flex-col"> |
| #95 | <span className="font-medium">{appConfig.name}</span> |
| #96 | <span className="text-zinc-400 text-sm"> |
| #97 | {new Date(entry.accessed_at + "Z").toLocaleDateString( |
| #98 | "en-US", |
| #99 | { |
| #100 | year: "numeric", |
| #101 | month: "short", |
| #102 | day: "numeric", |
| #103 | hour: "numeric", |
| #104 | minute: "numeric", |
| #105 | } |
| #106 | )} |
| #107 | </span> |
| #108 | </div> |
| #109 | </li> |
| #110 | ); |
| #111 | })} |
| #112 | </ul> |
| #113 | </ScrollArea> |
| #114 | </div> |
| #115 | ); |
| #116 | } |
| #117 |