mirror of
https://github.com/linkwarden/linkwarden.git
synced 2026-03-03 03:47:02 +00:00
133 lines
4.4 KiB
TypeScript
133 lines
4.4 KiB
TypeScript
import { View, Text, Pressable, Platform, Alert } from "react-native";
|
|
import { decode } from "html-entities";
|
|
import { CollectionIncludingMembersAndLinkCount } from "@linkwarden/types";
|
|
import useAuthStore from "@/store/auth";
|
|
import { useRouter } from "expo-router";
|
|
import * as ContextMenu from "zeego/context-menu";
|
|
import { cn } from "@linkwarden/lib/utils";
|
|
import { rawTheme, ThemeName } from "@/lib/colors";
|
|
import { useColorScheme } from "nativewind";
|
|
import { CalendarDays, Folder, Link } from "lucide-react-native";
|
|
import { useDeleteCollection } from "@linkwarden/router/collections";
|
|
|
|
type Props = {
|
|
collection: CollectionIncludingMembersAndLinkCount;
|
|
};
|
|
|
|
const CollectionListing = ({ collection }: Props) => {
|
|
const { auth } = useAuthStore();
|
|
const router = useRouter();
|
|
const { colorScheme } = useColorScheme();
|
|
|
|
const deleteCollection = useDeleteCollection(auth);
|
|
|
|
return (
|
|
<ContextMenu.Root>
|
|
<ContextMenu.Trigger asChild>
|
|
<Pressable
|
|
className={cn(
|
|
"p-5 flex-row justify-between",
|
|
"bg-base-100",
|
|
Platform.OS !== "android" && "active:bg-base-200/50"
|
|
)}
|
|
onLongPress={() => {}}
|
|
onPress={() => router.navigate(`/collections/${collection.id}`)}
|
|
android_ripple={{
|
|
color: colorScheme === "dark" ? "rgba(255,255,255,0.2)" : "#ddd",
|
|
borderless: false,
|
|
}}
|
|
>
|
|
<View className="w-full">
|
|
<View className="w-[90%] flex-col justify-between gap-3">
|
|
<View className="flex flex-row gap-2 items-center pr-1.5 self-start rounded-md">
|
|
<Folder
|
|
size={16}
|
|
fill={collection.color || ""}
|
|
color={collection.color || ""}
|
|
/>
|
|
<Text
|
|
numberOfLines={2}
|
|
className="font-medium text-lg text-base-content"
|
|
>
|
|
{decode(collection.name)}
|
|
</Text>
|
|
</View>
|
|
{collection.description && (
|
|
<Text
|
|
numberOfLines={2}
|
|
className="font-light text-sm text-base-content"
|
|
>
|
|
{decode(collection.description)}
|
|
</Text>
|
|
)}
|
|
</View>
|
|
|
|
<View className="flex-row gap-3">
|
|
<View className="flex flex-row gap-1 items-center mt-5 self-start">
|
|
<CalendarDays
|
|
size={16}
|
|
color={rawTheme[colorScheme as ThemeName]["neutral"]}
|
|
/>
|
|
<Text
|
|
numberOfLines={1}
|
|
className="font-light text-xs text-base-content"
|
|
>
|
|
{new Date(collection.createdAt as string).toLocaleString(
|
|
"en-US",
|
|
{
|
|
year: "numeric",
|
|
month: "short",
|
|
day: "numeric",
|
|
}
|
|
)}
|
|
</Text>
|
|
</View>
|
|
<View className="flex flex-row gap-1 items-center mt-5 self-start">
|
|
<Link
|
|
size={16}
|
|
color={rawTheme[colorScheme as ThemeName]["neutral"]}
|
|
/>
|
|
<Text
|
|
numberOfLines={1}
|
|
className="font-light text-xs text-base-content"
|
|
>
|
|
{collection._count?.links}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</Pressable>
|
|
</ContextMenu.Trigger>
|
|
|
|
<ContextMenu.Content avoidCollisions>
|
|
<ContextMenu.Item
|
|
key="delete-collection"
|
|
onSelect={() => {
|
|
return Alert.alert(
|
|
"Delete Collection",
|
|
"Are you sure you want to delete this collection? This action cannot be undone.",
|
|
[
|
|
{
|
|
text: "Cancel",
|
|
style: "cancel",
|
|
},
|
|
{
|
|
text: "Delete",
|
|
style: "destructive",
|
|
onPress: () => {
|
|
deleteCollection.mutate(collection.id as number);
|
|
},
|
|
},
|
|
]
|
|
);
|
|
}}
|
|
>
|
|
<ContextMenu.ItemTitle>Delete</ContextMenu.ItemTitle>
|
|
</ContextMenu.Item>
|
|
</ContextMenu.Content>
|
|
</ContextMenu.Root>
|
|
);
|
|
};
|
|
|
|
export default CollectionListing;
|