el.xwx.moe/store/links.ts

301 lines
8.0 KiB
TypeScript
Raw Normal View History

2023-03-05 15:03:20 -06:00
import { create } from "zustand";
import {
ArchivedFormat,
LinkIncludingShortenedCollectionAndTags,
} from "@/types/global";
2023-03-25 09:17:34 -05:00
import useTagStore from "./tags";
import useCollectionStore from "./collections";
2023-03-05 15:03:20 -06:00
type ResponseObject = {
ok: boolean;
data: object | string;
};
2023-03-22 18:11:54 -05:00
type LinkStore = {
links: LinkIncludingShortenedCollectionAndTags[];
selectedLinks: LinkIncludingShortenedCollectionAndTags[];
setLinks: (
data: LinkIncludingShortenedCollectionAndTags[],
isInitialCall: boolean
) => void;
setSelectedLinks: (links: LinkIncludingShortenedCollectionAndTags[]) => void;
addLink: (
body: LinkIncludingShortenedCollectionAndTags
) => Promise<ResponseObject>;
uploadFile: (
link: LinkIncludingShortenedCollectionAndTags,
file: File
) => Promise<ResponseObject>;
2023-11-19 07:12:37 -06:00
getLink: (linkId: number, publicRoute?: boolean) => Promise<ResponseObject>;
updateLink: (
link: LinkIncludingShortenedCollectionAndTags
) => Promise<ResponseObject>;
2024-02-10 18:34:25 -06:00
updateLinks: (
links: LinkIncludingShortenedCollectionAndTags[],
2024-02-11 01:21:25 -06:00
removePreviousTags: boolean,
2024-02-10 18:34:25 -06:00
newData: Pick<
LinkIncludingShortenedCollectionAndTags,
"tags" | "collectionId"
>
) => Promise<ResponseObject>;
removeLink: (linkId: number) => Promise<ResponseObject>;
2024-02-10 00:37:48 -06:00
deleteLinksById: (linkIds: number[]) => Promise<ResponseObject>;
resetLinks: () => void;
2023-03-05 15:03:20 -06:00
};
2023-03-22 18:11:54 -05:00
const useLinkStore = create<LinkStore>()((set) => ({
2023-03-05 15:03:20 -06:00
links: [],
selectedLinks: [],
setLinks: async (data, isInitialCall) => {
isInitialCall &&
set(() => ({
links: [],
}));
set((state) => ({
2023-10-23 09:45:48 -05:00
// Filter duplicate links by id
links: [...state.links, ...data].reduce(
(links: LinkIncludingShortenedCollectionAndTags[], item) => {
if (!links.some((link) => link.id === item.id)) {
links.push(item);
}
return links;
},
[]
),
}));
2023-03-05 15:03:20 -06:00
},
setSelectedLinks: (links) => set({ selectedLinks: links }),
2023-04-24 16:30:40 -05:00
addLink: async (body) => {
const response = await fetch("/api/v1/links", {
2023-04-24 16:30:40 -05:00
body: JSON.stringify(body),
2023-03-05 15:03:20 -06:00
headers: {
"Content-Type": "application/json",
},
method: "POST",
});
const data = await response.json();
2023-03-28 10:11:34 -05:00
if (response.ok) {
2023-03-05 15:03:20 -06:00
set((state) => ({
links: [data.response, ...state.links],
2023-03-05 15:03:20 -06:00
}));
2023-03-28 10:11:34 -05:00
useTagStore.getState().setTags();
useCollectionStore.getState().setCollections();
}
2023-03-25 09:17:34 -05:00
return { ok: response.ok, data: data.response };
2023-03-05 15:03:20 -06:00
},
uploadFile: async (link, file) => {
let fileType: ArchivedFormat | null = null;
let linkType: "url" | "image" | "pdf" | null = null;
if (file?.type === "image/jpg" || file.type === "image/jpeg") {
fileType = ArchivedFormat.jpeg;
linkType = "image";
} else if (file.type === "image/png") {
fileType = ArchivedFormat.png;
linkType = "image";
} else if (file.type === "application/pdf") {
fileType = ArchivedFormat.pdf;
linkType = "pdf";
} else {
return { ok: false, data: "Invalid file type." };
}
const response = await fetch("/api/v1/links", {
body: JSON.stringify({
...link,
type: linkType,
name: link.name ? link.name : file.name,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
});
const data = await response.json();
const createdLink: LinkIncludingShortenedCollectionAndTags = data.response;
console.log(data);
if (response.ok) {
const formBody = new FormData();
file && formBody.append("file", file);
await fetch(
`/api/v1/archives/${(data as any).response.id}?format=${fileType}`,
{
body: formBody,
method: "POST",
}
);
// get file extension
const extension = file.name.split(".").pop() || "";
set((state) => ({
links: [
{
...createdLink,
image:
linkType === "image"
? `archives/${createdLink.collectionId}/${
createdLink.id + extension
}`
: null,
pdf:
linkType === "pdf"
? `archives/${createdLink.collectionId}/${
createdLink.id + ".pdf"
}`
: null,
},
...state.links,
],
}));
useTagStore.getState().setTags();
useCollectionStore.getState().setCollections();
}
return { ok: response.ok, data: data.response };
},
2023-11-19 07:12:37 -06:00
getLink: async (linkId, publicRoute) => {
const path = publicRoute
? `/api/v1/public/links/${linkId}`
: `/api/v1/links/${linkId}`;
const response = await fetch(path);
2023-10-28 23:57:24 -05:00
const data = await response.json();
if (response.ok) {
2023-10-30 14:20:15 -05:00
set((state) => {
const linkExists = state.links.some(
(link) => link.id === data.response.id
);
if (linkExists) {
return {
links: state.links.map((e) =>
e.id === data.response.id ? data.response : e
),
};
} else {
return {
links: [...state.links, data.response],
};
}
});
2023-12-06 15:13:11 -06:00
return data;
2023-10-28 23:57:24 -05:00
}
return { ok: response.ok, data: data.response };
},
2023-03-28 10:11:34 -05:00
updateLink: async (link) => {
const response = await fetch(`/api/v1/links/${link.id}`, {
2023-03-28 10:11:34 -05:00
body: JSON.stringify(link),
headers: {
"Content-Type": "application/json",
},
method: "PUT",
});
const data = await response.json();
if (response.ok) {
set((state) => ({
2023-05-01 05:07:01 -05:00
links: state.links.map((e) =>
e.id === data.response.id ? data.response : e
),
2023-03-28 10:11:34 -05:00
}));
useTagStore.getState().setTags();
2023-05-01 05:07:01 -05:00
useCollectionStore.getState().setCollections();
2023-03-28 10:11:34 -05:00
}
2023-05-27 12:49:09 -05:00
return { ok: response.ok, data: data.response };
2023-03-28 10:11:34 -05:00
},
2024-02-11 01:21:25 -06:00
updateLinks: async (links, removePreviousTags, newData) => {
2024-02-10 16:23:59 -06:00
const response = await fetch("/api/v1/links", {
2024-02-11 01:21:25 -06:00
body: JSON.stringify({ links, removePreviousTags, newData }),
2024-02-10 16:23:59 -06:00
headers: {
"Content-Type": "application/json",
},
method: "PUT",
});
const data = await response.json();
2024-02-10 01:38:19 -06:00
2024-02-10 16:23:59 -06:00
if (response.ok) {
set((state) => ({
links: state.links.map((e) =>
2024-02-11 01:21:25 -06:00
links.some((link) => link.id === e.id)
? {
2024-02-11 01:29:11 -06:00
...e,
2024-02-14 07:10:45 -06:00
collectionId: newData.collectionId ?? e.collectionId,
collection: {
...e.collection,
id: newData.collectionId ?? e.collection.id,
},
2024-02-11 01:29:11 -06:00
tags: removePreviousTags
? [...(newData.tags ?? [])]
: [...e.tags, ...(newData.tags ?? [])],
}
2024-02-11 01:21:25 -06:00
: e
2024-02-10 16:23:59 -06:00
),
}));
useTagStore.getState().setTags();
useCollectionStore.getState().setCollections();
}
return { ok: response.ok, data: data.response };
},
removeLink: async (linkId) => {
const response = await fetch(`/api/v1/links/${linkId}`, {
2023-03-23 10:25:17 -05:00
headers: {
"Content-Type": "application/json",
},
method: "DELETE",
});
const data = await response.json();
2023-03-28 10:11:34 -05:00
if (response.ok) {
2023-03-23 10:25:17 -05:00
set((state) => ({
links: state.links.filter((e) => e.id !== linkId),
2023-03-23 10:25:17 -05:00
}));
2023-03-28 10:11:34 -05:00
useTagStore.getState().setTags();
2023-10-23 09:45:48 -05:00
useCollectionStore.getState().setCollections();
2023-03-28 10:11:34 -05:00
}
2023-03-23 10:25:17 -05:00
return { ok: response.ok, data: data.response };
2023-03-05 15:03:20 -06:00
},
2024-02-10 00:37:48 -06:00
deleteLinksById: async (linkIds: number[]) => {
2024-02-10 02:29:15 -06:00
const response = await fetch("/api/v1/links", {
2024-02-10 00:37:48 -06:00
body: JSON.stringify({ linkIds }),
headers: {
"Content-Type": "application/json",
},
method: "DELETE",
});
const data = await response.json();
if (response.ok) {
set((state) => ({
2024-02-10 16:59:00 -06:00
links: state.links.filter((e) => !linkIds.includes(e.id as number)),
2024-02-10 00:37:48 -06:00
}));
useTagStore.getState().setTags();
useCollectionStore.getState().setCollections();
}
return { ok: response.ok, data: data.response };
},
resetLinks: () => set({ links: [] }),
2023-03-05 15:03:20 -06:00
}));
2023-03-22 18:11:54 -05:00
export default useLinkStore;