feat(mobile): add collection functionality

This commit is contained in:
daniel31x13
2025-11-16 06:03:43 -05:00
parent 8f1612d10b
commit bebbf5ad80
4 changed files with 110 additions and 10 deletions

View File

@@ -54,9 +54,12 @@ export default function RootLayout() {
>
<DropdownMenu.ItemTitle>New Link</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
<DropdownMenu.Item key="more-options" disabled>
<DropdownMenu.Item
key="new-collection"
onSelect={() => SheetManager.show("new-collection-sheet")}
>
<DropdownMenu.ItemTitle>
More Coming Soon!
New Collection
</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
</DropdownMenu.Content>

View File

@@ -0,0 +1,88 @@
import { Alert, Text, View } from "react-native";
import { useRef, useState } from "react";
import ActionSheet, { ActionSheetRef } from "react-native-actions-sheet";
import Input from "@/components/ui/Input";
import { Button } from "@/components/ui/Button";
import useAuthStore from "@/store/auth";
import { rawTheme, ThemeName } from "@/lib/colors";
import { useColorScheme } from "nativewind";
import { useCreateCollection } from "@linkwarden/router/collections";
export default function NewCollectionSheet() {
const actionSheetRef = useRef<ActionSheetRef>(null);
const { auth } = useAuthStore();
const createCollection = useCreateCollection(auth);
const [collection, setCollection] = useState({
name: "",
description: "",
});
const { colorScheme } = useColorScheme();
return (
<ActionSheet
ref={actionSheetRef}
gestureEnabled
indicatorStyle={{
backgroundColor: rawTheme[colorScheme as ThemeName]["neutral-content"],
}}
containerStyle={{
backgroundColor: rawTheme[colorScheme as ThemeName]["base-200"],
}}
>
<View className="px-8 py-5">
<Input
placeholder="Name"
className="mb-4 bg-base-100"
value={collection.name}
onChangeText={(text) => setCollection({ ...collection, name: text })}
/>
<Input
placeholder="Description"
className="mb-4 bg-base-100"
value={collection.description}
onChangeText={(text) =>
setCollection({ ...collection, description: text })
}
/>
<Button
onPress={() =>
createCollection.mutate(
{ name: collection.name, description: collection.description },
{
onSuccess: () => {
actionSheetRef.current?.hide();
setCollection({ name: "", description: "" });
},
onError: (error) => {
Alert.alert(
"Error",
"There was an error creating the collection."
);
console.error("Error creating collection:", error);
},
}
)
}
isLoading={createCollection.isPending}
variant="accent"
className="mb-2"
>
<Text className="text-white">Save Collection</Text>
</Button>
<Button
onPress={() => {
actionSheetRef.current?.hide();
setCollection({ name: "", description: "" });
}}
variant="outline"
className="mb-2"
>
<Text className="text-base-content">Cancel</Text>
</Button>
</View>
</ActionSheet>
);
}

View File

@@ -6,11 +6,13 @@ import {
import SupportSheet from "./SupportSheet";
import AddLinkSheet from "./AddLinkSheet";
import EditLinkSheet from "./EditLinkSheet";
import NewCollectionSheet from "./NewCollectionSheet";
import { LinkIncludingShortenedCollectionAndTags } from "@linkwarden/types";
registerSheet("support-sheet", SupportSheet);
registerSheet("add-link-sheet", AddLinkSheet);
registerSheet("edit-link-sheet", EditLinkSheet);
registerSheet("new-collection-sheet", NewCollectionSheet);
declare module "react-native-actions-sheet" {
interface Sheets {
@@ -29,6 +31,7 @@ declare module "react-native-actions-sheet" {
}>;
};
}>;
"new-collection-sheet": SheetDefinition;
}
}

View File

@@ -37,18 +37,24 @@ const useCollections = (auth?: MobileAuth) => {
});
};
const useCreateCollection = () => {
const useCreateCollection = (auth?: MobileAuth) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (body: any) => {
const response = await fetch("/api/v1/collections", {
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
},
method: "POST",
});
const response = await fetch(
(auth?.instance ? auth?.instance : "") + "/api/v1/collections",
{
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
...(auth?.session
? { Authorization: `Bearer ${auth.session}` }
: {}),
},
method: "POST",
}
);
const data = await response.json();