aboutsummaryrefslogtreecommitdiffstats
path: root/packages/mobile/components/bookmarks/BookmarkCard.tsx
blob: 17e675dfe915a33431eec959ab4f00eccf6e6b52 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
import { ZBookmarkTags } from "@hoarder/trpc/types/tags";
import { Star, Archive, Trash } from "lucide-react-native";
import { View, Text, Image, ScrollView, Pressable } from "react-native";

import { api } from "@/lib/trpc";

function ActionBar({ bookmark }: { bookmark: ZBookmark }) {
  const apiUtils = api.useUtils();

  const { mutate: deleteBookmark } = api.bookmarks.deleteBookmark.useMutation({
    onSuccess: () => {
      apiUtils.bookmarks.getBookmarks.invalidate();
    },
  });
  const { mutate: updateBookmark, variables } =
    api.bookmarks.updateBookmark.useMutation({
      onSuccess: () => {
        apiUtils.bookmarks.getBookmarks.invalidate();
        apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: bookmark.id });
      },
    });

  return (
    <View className="flex flex-row gap-4">
      <Pressable
        onPress={() =>
          updateBookmark({
            bookmarkId: bookmark.id,
            favourited: !bookmark.favourited,
          })
        }
      >
        {(variables ? variables.favourited : bookmark.favourited) ? (
          <Star fill="#ebb434" color="#ebb434" />
        ) : (
          <Star />
        )}
      </Pressable>
      <Pressable
        onPress={() =>
          updateBookmark({
            bookmarkId: bookmark.id,
            archived: !bookmark.archived,
          })
        }
      >
        <Archive />
      </Pressable>
      <Pressable
        onPress={() =>
          deleteBookmark({
            bookmarkId: bookmark.id,
          })
        }
      >
        <Trash />
      </Pressable>
    </View>
  );
}

function TagList({ tags }: { tags: ZBookmarkTags[] }) {
  return (
    <ScrollView horizontal showsHorizontalScrollIndicator={false}>
      <View className="flex flex-row gap-2">
        {tags.map((t) => (
          <View className="rounded-full border border-gray-200 px-2.5 py-0.5 text-xs font-semibold">
            <Text>{t.name}</Text>
          </View>
        ))}
      </View>
    </ScrollView>
  );
}

function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
  if (bookmark.content.type !== "link") {
    throw new Error("Wrong content type rendered");
  }

  const parsedUrl = new URL(bookmark.content.url);

  return (
    <View className="flex gap-2 rounded bg-white p-4">
      <Image
        source={{ uri: bookmark.content.imageUrl || "" }}
        className="h-56 min-h-56 w-full"
      />
      <Text className="line-clamp-2 text-xl font-bold">
        {bookmark.content.title || parsedUrl.host}
      </Text>
      <TagList tags={bookmark.tags} />
      <View className="mt-2 flex flex-row justify-between">
        <Text className="my-auto line-clamp-1">{parsedUrl.host}</Text>
        <ActionBar bookmark={bookmark} />
      </View>
    </View>
  );
}

function TextCard({ bookmark }: { bookmark: ZBookmark }) {
  return <View />;
}

export default function BookmarkCard({
  bookmark: initialData,
}: {
  bookmark: ZBookmark;
}) {
  const { data: bookmark } = api.bookmarks.getBookmark.useQuery(
    {
      bookmarkId: initialData.id,
    },
    { initialData },
  );

  switch (bookmark.content.type) {
    case "link":
      return <LinkCard bookmark={bookmark} />;
    case "text":
      return <TextCard bookmark={bookmark} />;
  }
}