diff options
Diffstat (limited to 'apps/web/components/new/document-cards')
4 files changed, 43 insertions, 273 deletions
diff --git a/apps/web/components/new/document-cards/file-preview.tsx b/apps/web/components/new/document-cards/file-preview.tsx index 93e53463..f30645dc 100644 --- a/apps/web/components/new/document-cards/file-preview.tsx +++ b/apps/web/components/new/document-cards/file-preview.tsx @@ -5,71 +5,12 @@ import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api" import type { z } from "zod" import { dmSansClassName } from "@/lib/fonts" import { cn } from "@lib/utils" -import { PDF } from "@ui/assets/icons" -import { FileText, Image, Video } from "lucide-react" +import { DocumentIcon } from "@/components/new/document-icon" type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema> type DocumentWithMemories = DocumentsResponse["documents"][0] -function PDFIcon() { - return ( - <svg - width="8" - height="10" - viewBox="0 0 8 10" - fill="none" - xmlns="http://www.w3.org/2000/svg" - > - <title>PDF Icon</title> - <g filter="url(#filter0_i_719_6586)"> - <path - d="M1 10C0.725 10 0.489583 9.90208 0.29375 9.70625C0.0979167 9.51042 0 9.275 0 9V1C0 0.725 0.0979167 0.489583 0.29375 0.29375C0.489583 0.0979167 0.725 0 1 0H5L8 3V9C8 9.275 7.90208 9.51042 7.70625 9.70625C7.51042 9.90208 7.275 10 7 10H1ZM4.5 3.5V1H1V9H7V3.5H4.5Z" - fill="#FF7673" - /> - </g> - <defs> - <filter - id="filter0_i_719_6586" - x="0" - y="0" - width="8.25216" - height="10.2522" - filterUnits="userSpaceOnUse" - color-interpolation-filters="sRGB" - > - <feFlood flood-opacity="0" result="BackgroundImageFix" /> - <feBlend - mode="normal" - in="SourceGraphic" - in2="BackgroundImageFix" - result="shape" - /> - <feColorMatrix - in="SourceAlpha" - type="matrix" - values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" - result="hardAlpha" - /> - <feOffset dx="0.252163" dy="0.252163" /> - <feGaussianBlur stdDeviation="0.504325" /> - <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" /> - <feColorMatrix - type="matrix" - values="0 0 0 0 0.0431373 0 0 0 0 0.0588235 0 0 0 0 0.0823529 0 0 0 0.4 0" - /> - <feBlend - mode="normal" - in2="shape" - result="effect1_innerShadow_719_6586" - /> - </filter> - </defs> - </svg> - ) -} - function getFileTypeInfo(document: DocumentWithMemories): { - icon: React.ReactNode extension: string color?: string } { @@ -78,56 +19,33 @@ function getFileTypeInfo(document: DocumentWithMemories): { if (mimeType) { if (mimeType === "application/pdf") { - return { - icon: <PDFIcon />, - extension: ".pdf", - color: "#FF7673", - } + return { extension: ".pdf", color: "#FF7673" } } if (mimeType.startsWith("image/")) { const ext = mimeType.split("/")[1] || "jpg" - return { - icon: <Image className="w-4 h-4" style={{ color: "#FAFAFA" }} />, - extension: `.${ext}`, - } + return { extension: `.${ext}` } } if (mimeType.startsWith("video/")) { const ext = mimeType.split("/")[1] || "mp4" - return { - icon: <Video className="w-4 h-4" style={{ color: "#FAFAFA" }} />, - extension: `.${ext}`, - } + return { extension: `.${ext}` } } } switch (type) { case "pdf": - return { - icon: <PDF className="w-4 h-4 text-[#FF7673]" />, - extension: ".pdf", - color: "#FF7673", - } + return { extension: ".pdf", color: "#FF7673" } case "image": - return { - icon: <Image className="w-4 h-4" style={{ color: "#FAFAFA" }} />, - extension: ".jpg", - } + return { extension: ".jpg" } case "video": - return { - icon: <Video className="w-4 h-4" style={{ color: "#FAFAFA" }} />, - extension: ".mp4", - } + return { extension: ".mp4" } default: - return { - icon: <FileText className="w-4 h-4" style={{ color: "#FAFAFA" }} />, - extension: ".file", - } + return { extension: ".file" } } } export function FilePreview({ document }: { document: DocumentWithMemories }) { const [imageError, setImageError] = useState(false) - const { icon, extension, color } = getFileTypeInfo(document) + const { extension, color } = getFileTypeInfo(document) const type = document.type?.toLowerCase() const mimeType = document.metadata?.mimeType as string | undefined @@ -168,7 +86,7 @@ export function FilePreview({ document }: { document: DocumentWithMemories }) { ) : ( <div className="p-3"> <div className="flex items-center gap-1 mb-2"> - {icon} + <DocumentIcon type={document.type} url={document.url} className="w-4 h-4" /> <p className={cn(dmSansClassName(), "text-[10px] font-semibold")} style={{ color: color }} diff --git a/apps/web/components/new/document-cards/google-docs-preview.tsx b/apps/web/components/new/document-cards/google-docs-preview.tsx index 6c783c7d..50a56a16 100644 --- a/apps/web/components/new/document-cards/google-docs-preview.tsx +++ b/apps/web/components/new/document-cards/google-docs-preview.tsx @@ -4,6 +4,10 @@ import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api" import type { z } from "zod" import { dmSansClassName } from "@/lib/fonts" import { cn } from "@lib/utils" +import { + DocumentIcon, + getDocumentTypeLabel, +} from "@/components/new/document-icon" type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema> type DocumentWithMemories = DocumentsResponse["documents"][0] @@ -13,49 +17,28 @@ export function GoogleDocsPreview({ }: { document: DocumentWithMemories }) { + const label = getDocumentTypeLabel(document.type) + return ( <div className="bg-[#0B1017] p-3 rounded-[18px] gap-3"> <div className="flex items-center gap-2 mb-2"> - <svg - className="w-4 h-4" - xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 87.3 78" - aria-label="Google Docs" - > - <title>Google Docs</title> - <path - fill="#0066da" - d="m6.6 66.85 3.85 6.65c.8 1.4 1.95 2.5 3.3 3.3L27.5 53H0c0 1.55.4 3.1 1.2 4.5z" - /> - <path - fill="#00ac47" - d="M43.65 25 29.9 1.2c-1.35.8-2.5 1.9-3.3 3.3l-25.4 44A9.06 9.06 0 0 0 0 53h27.5z" - /> - <path - fill="#ea4335" - d="M73.55 76.8c1.35-.8 2.5-1.9 3.3-3.3l1.6-2.75L86.1 57.5c.8-1.4 1.2-2.95 1.2-4.5H59.798l5.852 11.5z" - /> - <path - fill="#00832d" - d="M43.65 25 57.4 1.2C56.05.4 54.5 0 52.9 0H34.4c-1.6 0-3.15.45-4.5 1.2z" - /> - <path - fill="#2684fc" - d="M59.8 53H27.5L13.75 76.8c1.35.8 2.9 1.2 4.5 1.2h50.8c1.6 0 3.15-.45 4.5-1.2z" - /> - <path - fill="#ffba00" - d="m73.4 26.5-12.7-22c-.8-1.4-1.95-2.5-3.3-3.3L43.65 25 59.8 53h27.45c0-1.55-.4-3.1-1.2-4.5z" - /> - </svg> + <DocumentIcon type={document.type} url={document.url} className="w-4 h-4" /> <p className={cn(dmSansClassName(), "text-[12px] font-semibold")}> - Google Docs + {label} </p> </div> - {document.content && ( + {document.summary ? ( + <p className="text-[10px] text-[#737373] line-clamp-4"> + {document.summary} + </p> + ) : document.content ? ( <p className="text-[10px] text-[#737373] line-clamp-4"> {document.content} </p> + ) : ( + <p className="text-[10px] text-[#737373] line-clamp-4"> + No summary available + </p> )} </div> ) diff --git a/apps/web/components/new/document-cards/note-preview.tsx b/apps/web/components/new/document-cards/note-preview.tsx index c2b767b0..3e684a88 100644 --- a/apps/web/components/new/document-cards/note-preview.tsx +++ b/apps/web/components/new/document-cards/note-preview.tsx @@ -4,138 +4,16 @@ import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api" import type { z } from "zod" import { dmSansClassName } from "@/lib/fonts" import { cn } from "@lib/utils" -import { useMemo } from "react" +import { DocumentIcon } from "@/components/new/document-icon" type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema> type DocumentWithMemories = DocumentsResponse["documents"][0] -type TipTapNode = { - type: string - text?: string - content?: TipTapNode[] - attrs?: Record<string, unknown> -} - -function extractTextFromTipTapContent(content: string): string { - try { - const json = JSON.parse(content) as TipTapNode - return extractTextFromNode(json) - } catch { - return content - } -} - -function extractTextFromNode(node: TipTapNode): string { - if (node.type === "text" && node.text) { - return node.text - } - - if (!node.content) { - return "" - } - - const texts: string[] = [] - for (const child of node.content) { - const text = extractTextFromNode(child) - if (text) { - texts.push(text) - } - } - - const blockTypes = [ - "paragraph", - "heading", - "listItem", - "blockquote", - "codeBlock", - ] - if (blockTypes.includes(node.type)) { - return `${texts.join("")}\n` - } - - return texts.join("") -} - -function NoteIcon() { - return ( - <svg - width="14" - height="14" - viewBox="0 0 14 14" - fill="none" - xmlns="http://www.w3.org/2000/svg" - > - <title>Note Icon</title> - <mask - id="mask0_344_4970" - style={{ maskType: "alpha" }} - maskUnits="userSpaceOnUse" - x="0" - y="0" - width="14" - height="14" - > - <rect width="14" height="14" fill="#D9D9D9" /> - </mask> - <g mask="url(#mask0_344_4970)"> - <g filter="url(#filter0_i_344_4970)"> - <path - d="M3.50002 8.75008H7.58335L8.75002 7.58341H3.50002V8.75008ZM3.50002 6.41675H7.00002V5.25008H3.50002V6.41675ZM2.33335 4.08341V9.91675H6.41669L5.25002 11.0834H1.16669V2.91675H12.8334V4.66675H11.6667V4.08341H2.33335ZM13.3584 7.17508C13.407 7.22369 13.4313 7.27716 13.4313 7.3355C13.4313 7.39383 13.407 7.4473 13.3584 7.49591L12.8334 8.02091L11.8125 7.00008L12.3375 6.47508C12.3861 6.42647 12.4396 6.40216 12.4979 6.40216C12.5563 6.40216 12.6097 6.42647 12.6584 6.47508L13.3584 7.17508ZM7.58335 12.2501V11.2292L11.4625 7.35008L12.4834 8.37091L8.60419 12.2501H7.58335Z" - fill="#FAFAFA" - /> - </g> - </g> - <defs> - <filter - id="filter0_i_344_4970" - x="1.16669" - y="2.91675" - width="12.6176" - height="9.68628" - filterUnits="userSpaceOnUse" - colorInterpolationFilters="sRGB" - > - <feFlood floodOpacity="0" result="BackgroundImageFix" /> - <feBlend - mode="normal" - in="SourceGraphic" - in2="BackgroundImageFix" - result="shape" - /> - <feColorMatrix - in="SourceAlpha" - type="matrix" - values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" - result="hardAlpha" - /> - <feOffset dx="0.353028" dy="0.353028" /> - <feGaussianBlur stdDeviation="0.706055" /> - <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" /> - <feColorMatrix - type="matrix" - values="0 0 0 0 0.0431373 0 0 0 0 0.0588235 0 0 0 0 0.0823529 0 0 0 0.4 0" - /> - <feBlend - mode="normal" - in2="shape" - result="effect1_innerShadow_344_4970" - /> - </filter> - </defs> - </svg> - ) -} - export function NotePreview({ document }: { document: DocumentWithMemories }) { - const previewText = useMemo(() => { - if (!document.content) return "" - return extractTextFromTipTapContent(document.content).trim() - }, [document.content]) - return ( <div className="bg-[#0B1017] p-3 rounded-[18px] space-y-2"> <div className="flex items-center gap-1"> - <NoteIcon /> + <DocumentIcon type="note" className="w-4 h-4" /> <p className={cn(dmSansClassName(), "text-[12px] font-semibold")}> Note </p> @@ -151,9 +29,9 @@ export function NotePreview({ document }: { document: DocumentWithMemories }) { {document.title} </p> )} - {previewText && ( + {document.summary && ( <p className="text-[10px] text-[#737373] line-clamp-4"> - {previewText} + {document.summary} </p> )} </div> diff --git a/apps/web/components/new/document-cards/website-preview.tsx b/apps/web/components/new/document-cards/website-preview.tsx index ab3c5ad3..21ae9de2 100644 --- a/apps/web/components/new/document-cards/website-preview.tsx +++ b/apps/web/components/new/document-cards/website-preview.tsx @@ -3,50 +3,41 @@ import { useState } from "react" import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api" import type { z } from "zod" -import { dmSansClassName } from "@/lib/fonts" -import { cn } from "@lib/utils" type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema> type DocumentWithMemories = DocumentsResponse["documents"][0] +type OgData = { + title?: string + image?: string +} + export function WebsitePreview({ document, + ogData, }: { document: DocumentWithMemories + ogData?: OgData | null }) { const [imageError, setImageError] = useState(false) + const ogImage = (document as DocumentWithMemories & { ogImage?: string }) .ogImage + const displayOgImage = ogImage || ogData?.image return ( <div className="bg-[#0B1017] rounded-[18px] overflow-hidden"> - {ogImage && !imageError ? ( + {displayOgImage && !imageError ? ( <div className="relative w-full aspect-video bg-gray-100 overflow-hidden"> <img - src={ogImage} + src={displayOgImage} alt={document.title || "Website preview"} className="w-full h-full object-cover" onError={() => setImageError(true)} loading="lazy" /> </div> - ) : ( - <div className="p-3 gap-2"> - <p - className={cn( - dmSansClassName(), - "text-[12px] font-semibold text-[#E5E5E5] line-clamp-2 mb-1", - )} - > - {document.title || "Untitled Document"} - </p> - {document.content && ( - <p className="text-[10px] text-[#737373] line-clamp-3"> - {document.content} - </p> - )} - </div> - )} + ) : null} </div> ) } |