mirror of
https://github.com/aljazceru/claude-code-viewer.git
synced 2026-01-01 12:44:24 +01:00
chore: format files
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { ArrowLeftIcon } from "lucide-react";
|
||||
import { ArrowLeftIcon, FolderIcon, MessageSquareIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { FolderIcon, MessageSquareIcon } from "lucide-react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -11,11 +10,9 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import { useProject } from "../hooks/useProject";
|
||||
import { pagesPath } from "../../../../lib/$path";
|
||||
import { parseCommandXml } from "../../../../server/service/parseCommandXml";
|
||||
import { useProject } from "../hooks/useProject";
|
||||
import { firstCommandToTitle } from "../services/firstCommandToTitle";
|
||||
|
||||
export const ProjectPageContent = ({ projectId }: { projectId: string }) => {
|
||||
const {
|
||||
@@ -78,31 +75,9 @@ export const ProjectPageContent = ({ projectId }: { projectId: string }) => {
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<span className="break-all overflow-ellipsis line-clamp-2 text-xl">
|
||||
{session.meta.firstContent
|
||||
? (() => {
|
||||
const parsed = parseCommandXml(
|
||||
session.meta.firstContent
|
||||
);
|
||||
if (parsed.kind === "command") {
|
||||
return (
|
||||
<span>
|
||||
{parsed.commandName} {parsed.commandArgs}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (parsed.kind === "local-command-1") {
|
||||
return (
|
||||
<span>
|
||||
{parsed.commandName} {parsed.commandMessage}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (parsed.kind === "local-command-2") {
|
||||
return <span>{parsed.stdout}</span>;
|
||||
}
|
||||
return <span>{session.meta.firstContent}</span>;
|
||||
})()
|
||||
: ""}
|
||||
{session.meta.firstCommand !== null
|
||||
? firstCommandToTitle(session.meta.firstCommand)
|
||||
: session.id}
|
||||
</span>
|
||||
</CardTitle>
|
||||
<CardDescription className="font-mono text-xs">
|
||||
@@ -117,7 +92,7 @@ export const ProjectPageContent = ({ projectId }: { projectId: string }) => {
|
||||
Last modified:{" "}
|
||||
{session.meta.lastModifiedAt
|
||||
? new Date(
|
||||
session.meta.lastModifiedAt
|
||||
session.meta.lastModifiedAt,
|
||||
).toLocaleDateString()
|
||||
: ""}
|
||||
</p>
|
||||
@@ -129,7 +104,7 @@ export const ProjectPageContent = ({ projectId }: { projectId: string }) => {
|
||||
<Button asChild className="w-full">
|
||||
<Link
|
||||
href={`/projects/${projectId}/sessions/${encodeURIComponent(
|
||||
session.id
|
||||
session.id,
|
||||
)}`}
|
||||
>
|
||||
View Session
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
|
||||
export default function ProjectLoading() {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<header className="mb-8">
|
||||
<Skeleton className="h-9 w-32 mb-4" />
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<Skeleton className="w-6 h-6" />
|
||||
<Skeleton className="h-9 w-80" />
|
||||
</div>
|
||||
<Skeleton className="h-4 w-96" />
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
<Skeleton className="h-7 w-64 mb-4" />
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{Array.from({ length: 6 }).map((_, index) => (
|
||||
<Card key={index}>
|
||||
<CardHeader>
|
||||
<Skeleton className="h-6 w-3/4" />
|
||||
<Skeleton className="h-4 w-1/2" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
<Skeleton className="h-4 w-24" />
|
||||
<Skeleton className="h-4 w-32" />
|
||||
<Skeleton className="h-3 w-full" />
|
||||
<Skeleton className="h-10 w-full mt-4" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
17
src/app/projects/[projectId]/services/firstCommandToTitle.ts
Normal file
17
src/app/projects/[projectId]/services/firstCommandToTitle.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { ParsedCommand } from "../../../../server/service/parseCommandXml";
|
||||
|
||||
export const firstCommandToTitle = (firstCommand: ParsedCommand) => {
|
||||
switch (firstCommand.kind) {
|
||||
case "command":
|
||||
return `${firstCommand.commandName} ${firstCommand.commandArgs}`;
|
||||
case "local-command-1":
|
||||
return firstCommand.commandMessage;
|
||||
case "local-command-2":
|
||||
return firstCommand.stdout;
|
||||
case "text":
|
||||
return firstCommand.content;
|
||||
default:
|
||||
firstCommand satisfies never;
|
||||
throw new Error("Invalid first command");
|
||||
}
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
const regExp = /<(?<tag>[^>]+)>(?<content>\s*[^<]*?\s*)<\/\k<tag>>/g;
|
||||
|
||||
export const parseCommandXml = (
|
||||
content: string
|
||||
content: string,
|
||||
):
|
||||
| {
|
||||
kind: "command";
|
||||
@@ -37,16 +37,16 @@ export const parseCommandXml = (
|
||||
}
|
||||
|
||||
const commandName = matches.find(
|
||||
(match) => match.tag === "command-name"
|
||||
(match) => match.tag === "command-name",
|
||||
)?.content;
|
||||
const commandArgs = matches.find(
|
||||
(match) => match.tag === "command-args"
|
||||
(match) => match.tag === "command-args",
|
||||
)?.content;
|
||||
const commandMessage = matches.find(
|
||||
(match) => match.tag === "command-message"
|
||||
(match) => match.tag === "command-message",
|
||||
)?.content;
|
||||
const localCommandStdout = matches.find(
|
||||
(match) => match.tag === "local-command-stdout"
|
||||
(match) => match.tag === "local-command-stdout",
|
||||
)?.content;
|
||||
|
||||
switch (true) {
|
||||
@@ -74,4 +74,4 @@ export const parseCommandXml = (
|
||||
content,
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"use client";
|
||||
|
||||
import { ArrowLeftIcon, MessageSquareIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import type { FC } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { firstCommandToTitle } from "../../../services/firstCommandToTitle";
|
||||
import { useSession } from "../hooks/useSession";
|
||||
import { ConversationList } from "./conversationList/ConversationList";
|
||||
|
||||
export const SessionPageContent: FC<{
|
||||
projectId: string;
|
||||
sessionId: string;
|
||||
}> = ({ projectId, sessionId }) => {
|
||||
const { session, conversations, getToolResult } = useSession(
|
||||
projectId,
|
||||
sessionId,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<header className="mb-8">
|
||||
<Button asChild variant="ghost" className="mb-4">
|
||||
<Link
|
||||
href={`/projects/${projectId}`}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<ArrowLeftIcon className="w-4 h-4" />
|
||||
Back to Session List
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<MessageSquareIcon className="w-6 h-6" />
|
||||
<h1 className="text-3xl font-bold">
|
||||
{session.meta.firstCommand !== null
|
||||
? firstCommandToTitle(session.meta.firstCommand)
|
||||
: sessionId}
|
||||
</h1>
|
||||
</div>
|
||||
<p className="text-muted-foreground font-mono text-sm">
|
||||
Session ID: {sessionId}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<ConversationList
|
||||
conversations={conversations}
|
||||
getToolResult={getToolResult}
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,12 +1,6 @@
|
||||
import { ToolResultContent } from "@/lib/conversation-schema/content/ToolResultContentSchema";
|
||||
import { AssistantMessageContent } from "@/lib/conversation-schema/message/AssistantMessageSchema";
|
||||
import { FC } from "react";
|
||||
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import { ChevronDown, FileText, Lightbulb, Settings } from "lucide-react";
|
||||
import type { FC } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -14,8 +8,13 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { ChevronDown, Lightbulb, Settings, FileText } from "lucide-react";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import type { ToolResultContent } from "@/lib/conversation-schema/content/ToolResultContentSchema";
|
||||
import type { AssistantMessageContent } from "@/lib/conversation-schema/message/AssistantMessageSchema";
|
||||
import { MarkdownContent } from "../../../../../../components/MarkdownContent";
|
||||
|
||||
export const AssistantConversationContent: FC<{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { FC } from "react";
|
||||
import type { Conversation } from "@/lib/conversation-schema";
|
||||
import type { ToolResultContent } from "@/lib/conversation-schema/content/ToolResultContentSchema";
|
||||
import type { FC } from "react";
|
||||
import { UserConversationContent } from "./UserConversationContent";
|
||||
import { AssistantConversationContent } from "./AssistantConversationContent";
|
||||
import { MetaConversationContent } from "./MetaConversationContent";
|
||||
import { SystemConversationContent } from "./SystemConversationContent";
|
||||
import { SummaryConversationContent } from "./SummaryConversationContent";
|
||||
import { SystemConversationContent } from "./SystemConversationContent";
|
||||
import { UserConversationContent } from "./UserConversationContent";
|
||||
|
||||
export const ConversationItem: FC<{
|
||||
conversation: Conversation;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import type { Conversation } from "@/lib/conversation-schema";
|
||||
import type { FC } from "react";
|
||||
import { useConversations } from "../../hooks/useConversations";
|
||||
import type { Conversation } from "@/lib/conversation-schema";
|
||||
import type { ToolResultContent } from "@/lib/conversation-schema/content/ToolResultContentSchema";
|
||||
import { ConversationItem } from "./ConversationItem";
|
||||
|
||||
const getConversationKey = (conversation: Conversation) => {
|
||||
@@ -26,19 +26,14 @@ const getConversationKey = (conversation: Conversation) => {
|
||||
};
|
||||
|
||||
type ConversationListProps = {
|
||||
projectId: string;
|
||||
sessionId: string;
|
||||
conversations: Conversation[];
|
||||
getToolResult: (toolUseId: string) => ToolResultContent | undefined;
|
||||
};
|
||||
|
||||
export const ConversationList: FC<ConversationListProps> = ({
|
||||
projectId,
|
||||
sessionId,
|
||||
conversations,
|
||||
getToolResult,
|
||||
}) => {
|
||||
const { conversations, getToolResult } = useConversations(
|
||||
projectId,
|
||||
sessionId
|
||||
);
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{conversations.flatMap((conversation) => {
|
||||
@@ -60,8 +55,8 @@ export const ConversationList: FC<ConversationListProps> = ({
|
||||
conversation.type === "user"
|
||||
? "justify-end"
|
||||
: conversation.type === "assistant"
|
||||
? "justify-start"
|
||||
: "justify-center"
|
||||
? "justify-start"
|
||||
: "justify-center"
|
||||
}`}
|
||||
key={getConversationKey(conversation)}
|
||||
>
|
||||
@@ -70,8 +65,8 @@ export const ConversationList: FC<ConversationListProps> = ({
|
||||
conversation.type === "user"
|
||||
? "w-[90%]"
|
||||
: conversation.type === "assistant"
|
||||
? "w-[90%]"
|
||||
: "w-[100%]"
|
||||
? "w-[90%]"
|
||||
: "w-[100%]"
|
||||
}`}
|
||||
>
|
||||
{elm}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
export const MetaConversationContent: FC<PropsWithChildren> = ({
|
||||
children,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
export const SummaryConversationContent: FC<PropsWithChildren> = ({
|
||||
children,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
export const SystemConversationContent: FC<PropsWithChildren> = ({
|
||||
children,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { FC } from "react";
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Terminal } from "lucide-react";
|
||||
import type { FC } from "react";
|
||||
import { parseCommandXml } from "@/app/projects/[projectId]/services/parseCommandXml";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { MarkdownContent } from "../../../../../../components/MarkdownContent";
|
||||
|
||||
export const TextContent: FC<{ text: string }> = ({ text }) => {
|
||||
@@ -11,7 +10,7 @@ export const TextContent: FC<{ text: string }> = ({ text }) => {
|
||||
|
||||
if (parsed.kind === "command") {
|
||||
return (
|
||||
<Card className="border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20 gap-2 py-3">
|
||||
<Card className="border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20 gap-2 py-3 mb-3">
|
||||
<CardHeader className="py-0 px-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4 text-green-600 dark:text-green-400" />
|
||||
@@ -46,7 +45,7 @@ export const TextContent: FC<{ text: string }> = ({ text }) => {
|
||||
|
||||
if (parsed.kind === "local-command-1") {
|
||||
return (
|
||||
<Card className="border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20 gap-2 py-3">
|
||||
<Card className="border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20 gap-2 py-3 mb-3">
|
||||
<CardHeader className="py-0 px-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4 text-green-600 dark:text-green-400" />
|
||||
@@ -62,7 +61,7 @@ export const TextContent: FC<{ text: string }> = ({ text }) => {
|
||||
|
||||
if (parsed.kind === "local-command-2") {
|
||||
return (
|
||||
<Card className="border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20 gap-2 py-3">
|
||||
<Card className="border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20 gap-2 py-3 mb-3">
|
||||
<CardHeader className="py-0 px-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4 text-green-600 dark:text-green-400" />
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { UserMessageContent } from "@/lib/conversation-schema/message/UserMessageSchema";
|
||||
import { AlertCircle, Image as ImageIcon } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import type { FC } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -7,8 +9,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Image as ImageIcon, AlertCircle } from "lucide-react";
|
||||
import type { UserMessageContent } from "@/lib/conversation-schema/message/UserMessageSchema";
|
||||
import { TextContent } from "./TextContent";
|
||||
|
||||
export const UserConversationContent: FC<{
|
||||
@@ -43,7 +44,7 @@ export const UserConversationContent: FC<{
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="rounded-lg border overflow-hidden bg-background">
|
||||
<img
|
||||
<Image
|
||||
src={`data:${content.source.media_type};base64,${content.source.data}`}
|
||||
alt="User uploaded content"
|
||||
className="max-w-full h-auto max-h-96 object-contain"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useConversationsQuery } from "./useConversationsQuery";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useSessionQuery } from "./useSessionQuery";
|
||||
|
||||
export const useConversations = (projectId: string, sessionId: string) => {
|
||||
const query = useConversationsQuery(projectId, sessionId);
|
||||
export const useSession = (projectId: string, sessionId: string) => {
|
||||
const query = useSessionQuery(projectId, sessionId);
|
||||
|
||||
const toolResultMap = useMemo(() => {
|
||||
const entries = query.data.session.conversations.flatMap((conversation) => {
|
||||
@@ -34,10 +34,11 @@ export const useConversations = (projectId: string, sessionId: string) => {
|
||||
(toolUseId: string) => {
|
||||
return toolResultMap.get(toolUseId);
|
||||
},
|
||||
[toolResultMap]
|
||||
[toolResultMap],
|
||||
);
|
||||
|
||||
return {
|
||||
session: query.data.session,
|
||||
conversations: query.data.session.conversations,
|
||||
getToolResult,
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||
import { honoClient } from "../../../../../../lib/api/client";
|
||||
|
||||
export const useConversationsQuery = (projectId: string, sessionId: string) => {
|
||||
export const useSessionQuery = (projectId: string, sessionId: string) => {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ["conversations", sessionId],
|
||||
queryFn: async () => {
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
|
||||
export default function SessionLoading() {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<header className="mb-8">
|
||||
<Skeleton className="h-9 w-32 mb-4" />
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<Skeleton className="w-6 h-6" />
|
||||
<Skeleton className="h-9 w-64" />
|
||||
</div>
|
||||
<Skeleton className="h-4 w-80" />
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<Card className="max-w-4xl mx-auto">
|
||||
<CardHeader>
|
||||
<Skeleton className="h-6 w-48" />
|
||||
<Skeleton className="h-4 w-64" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<Skeleton className="h-32 w-full" />
|
||||
<Skeleton className="h-24 w-full" />
|
||||
<Skeleton className="h-16 w-full" />
|
||||
<div className="flex justify-center pt-4">
|
||||
<Skeleton className="h-10 w-32" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
import Link from "next/link";
|
||||
import { ArrowLeftIcon, MessageSquareIcon } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { Metadata } from "next";
|
||||
import { ConversationList } from "./components/conversationList/ConversationList";
|
||||
import { SessionPageContent } from "./components/SessionPageContent";
|
||||
|
||||
type PageParams = {
|
||||
projectId: string;
|
||||
@@ -28,31 +25,5 @@ interface SessionPageProps {
|
||||
export default async function SessionPage({ params }: SessionPageProps) {
|
||||
const { projectId, sessionId } = await params;
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<header className="mb-8">
|
||||
<Button asChild variant="ghost" className="mb-4">
|
||||
<Link
|
||||
href={`/projects/${projectId}`}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<ArrowLeftIcon className="w-4 h-4" />
|
||||
Back to Session List
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<MessageSquareIcon className="w-6 h-6" />
|
||||
<h1 className="text-3xl font-bold">Conversation Session</h1>
|
||||
</div>
|
||||
<p className="text-muted-foreground font-mono text-sm">
|
||||
Session ID: {sessionId}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<ConversationList projectId={projectId} sessionId={sessionId} />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
return <SessionPageContent projectId={projectId} sessionId={sessionId} />;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import type { FC } from "react";
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
} from "@/components/ui/card";
|
||||
import { FolderIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import type { FC } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { useProjects } from "../hooks/useProjects";
|
||||
|
||||
export const ProjectList: FC = () => {
|
||||
|
||||
Reference in New Issue
Block a user