From 5ecdc36b7d60aa66b49e01e9fec8ba61ad537376 Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Thu, 2 Jan 2025 13:00:58 +0200
Subject: feat: Add support for smart lists (#802)

* feat: Add support for smart lists

* i18n

* Fix update list endpoint

* Add a test for smart lists

* Add header to the query explainer

* Hide remove from lists in the smart context list

* Add proper validation to list form

---------

Co-authored-by: Deepak Kapoor <41769111+orthdron@users.noreply.github.com>
---
 apps/web/components/dashboard/lists/ListHeader.tsx | 38 ++++++++++++++++++----
 1 file changed, 32 insertions(+), 6 deletions(-)

(limited to 'apps/web/components/dashboard/lists/ListHeader.tsx')

diff --git a/apps/web/components/dashboard/lists/ListHeader.tsx b/apps/web/components/dashboard/lists/ListHeader.tsx
index a6780e1e..b8bfb4ad 100644
--- a/apps/web/components/dashboard/lists/ListHeader.tsx
+++ b/apps/web/components/dashboard/lists/ListHeader.tsx
@@ -1,19 +1,24 @@
 "use client";
 
+import { useMemo } from "react";
 import { useRouter } from "next/navigation";
 import { Button } from "@/components/ui/button";
-import { MoreHorizontal } from "lucide-react";
+import { useTranslation } from "@/lib/i18n/client";
+import { MoreHorizontal, SearchIcon } from "lucide-react";
 
 import { api } from "@hoarder/shared-react/trpc";
+import { parseSearchQuery } from "@hoarder/shared/searchQueryParser";
 import { ZBookmarkList } from "@hoarder/shared/types/lists";
 
+import QueryExplainerTooltip from "../search/QueryExplainerTooltip";
 import { ListOptions } from "./ListOptions";
 
 export default function ListHeader({
   initialData,
 }: {
-  initialData: ZBookmarkList & { bookmarks: string[] };
+  initialData: ZBookmarkList;
 }) {
+  const { t } = useTranslation();
   const router = useRouter();
   const { data: list, error } = api.lists.get.useQuery(
     {
@@ -24,6 +29,13 @@ export default function ListHeader({
     },
   );
 
+  const parsedQuery = useMemo(() => {
+    if (!list.query) {
+      return null;
+    }
+    return parseSearchQuery(list.query);
+  }, [list.query]);
+
   if (error) {
     // This is usually exercised during list deletions.
     if (error.data?.code == "NOT_FOUND") {
@@ -33,10 +45,24 @@ export default function ListHeader({
 
   return (
     <div className="flex items-center justify-between">
-      <span className="text-2xl">
-        {list.icon} {list.name}
-      </span>
-      <div className="flex">
+      <div className="flex items-center gap-2">
+        <span className="text-2xl">
+          {list.icon} {list.name}
+        </span>
+      </div>
+      <div className="flex items-center">
+        {parsedQuery && (
+          <QueryExplainerTooltip
+            header={
+              <div className="flex items-center justify-center gap-1">
+                <SearchIcon className="size-3" />
+                <span className="text-sm">{t("lists.smart_list")}</span>
+              </div>
+            }
+            parsedSearchQuery={parsedQuery}
+            className="size-6 stroke-foreground"
+          />
+        )}
         <ListOptions list={list}>
           <Button variant="ghost">
             <MoreHorizontal />
-- 
cgit v1.2.3-70-g09d2

