ui improvements
This commit is contained in:
parent
2e3ec53d2a
commit
3a5ae28f86
|
@ -40,7 +40,7 @@ export default function ({ toggleLinkModal }: { toggleLinkModal: Function }) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="slide-up border-sky-100 border-solid border rounded-md shadow-lg p-5 bg-white flex flex-col gap-3">
|
<div className="slide-up border-sky-100 rounded-md border-solid border rounded-md-md shadow-lg p-5 bg-white flex flex-col gap-3">
|
||||||
<p className="font-bold text-sky-300 mb-2 text-center">New Link</p>
|
<p className="font-bold text-sky-300 mb-2 text-center">New Link</p>
|
||||||
|
|
||||||
<div className="flex gap-5 items-center justify-between">
|
<div className="flex gap-5 items-center justify-between">
|
||||||
|
@ -50,7 +50,7 @@ export default function ({ toggleLinkModal }: { toggleLinkModal: Function }) {
|
||||||
onChange={(e) => setNewLink({ ...newLink, name: e.target.value })}
|
onChange={(e) => setNewLink({ ...newLink, name: e.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="e.g. Example Link"
|
placeholder="e.g. Example Link"
|
||||||
className="w-60 rounded p-3 border-sky-100 border-solid border text-sm outline-none focus:border-sky-500 duration-100"
|
className="w-60 rounded-md p-3 border-sky-100 border-solid border text-sm outline-none focus:border-sky-500 duration-100"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ export default function ({ toggleLinkModal }: { toggleLinkModal: Function }) {
|
||||||
onChange={(e) => setNewLink({ ...newLink, url: e.target.value })}
|
onChange={(e) => setNewLink({ ...newLink, url: e.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="e.g. http://example.com/"
|
placeholder="e.g. http://example.com/"
|
||||||
className="w-60 rounded p-3 border-sky-100 border-solid border text-sm outline-none focus:border-sky-500 duration-100"
|
className="w-60 rounded-md p-3 border-sky-100 border-solid border text-sm outline-none focus:border-sky-500 duration-100"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ export default function ({ toggleLinkModal }: { toggleLinkModal: Function }) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="mx-auto mt-2 bg-sky-500 text-white flex items-center gap-2 py-2 px-5 rounded select-none font-bold cursor-pointer duration-100 hover:bg-sky-400"
|
className="mx-auto mt-2 bg-sky-500 text-white flex items-center gap-2 py-2 px-5 rounded-md select-none font-bold cursor-pointer duration-100 hover:bg-sky-400"
|
||||||
onClick={submitLink}
|
onClick={submitLink}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faPlus} className="h-5" />
|
<FontAwesomeIcon icon={faPlus} className="h-5" />
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default function ({ collection }: { collection: Collection }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/collections/${collection.id}`}>
|
<Link href={`/collections/${collection.id}`}>
|
||||||
<div className="p-5 bg-gray-100 m-2 h-40 w-60 rounded border-sky-100 border-solid border flex flex-col justify-between cursor-pointer hover:bg-gray-50 duration-100">
|
<div className="p-5 bg-gray-100 h-40 w-60 rounded-md border-sky-100 border-solid border flex flex-col justify-between cursor-pointer hover:bg-gray-50 duration-100">
|
||||||
<div className="flex justify-between text-sky-900 items-center">
|
<div className="flex justify-between text-sky-900 items-center">
|
||||||
<p className="text-lg w-max">{collection.name}</p>
|
<p className="text-lg w-max">{collection.name}</p>
|
||||||
<FontAwesomeIcon icon={faChevronRight} className="w-3" />
|
<FontAwesomeIcon icon={faChevronRight} className="w-3" />
|
||||||
|
|
|
@ -19,12 +19,12 @@ export default function ({ onClickOutside, className, items }: Props) {
|
||||||
return (
|
return (
|
||||||
<ClickAwayHandler
|
<ClickAwayHandler
|
||||||
onClickOutside={onClickOutside}
|
onClickOutside={onClickOutside}
|
||||||
className={`${className} border border-sky-100 shadow mb-5 bg-gray-50 rounded flex flex-col `}
|
className={`${className} border border-sky-100 shadow-md mb-5 bg-gray-50 rounded-md flex flex-col w-36`}
|
||||||
>
|
>
|
||||||
{items.map((e, i) => {
|
{items.map((e, i) => {
|
||||||
const inner = (
|
const inner = (
|
||||||
<div className="cursor-pointer hover:bg-white hover:outline outline-sky-100 outline-1 duration-100">
|
<div className="cursor-pointer rounded-md hover:bg-white hover:outline outline-sky-100 outline-1 duration-100">
|
||||||
<div className="flex items-center gap-2 p-2 rounded hover:opacity-60 duration-100">
|
<div className="flex items-center gap-2 p-2 rounded-md hover:opacity-60 duration-100">
|
||||||
{React.cloneElement(e.icon, {
|
{React.cloneElement(e.icon, {
|
||||||
className: "text-sky-500 w-5 h-5",
|
className: "text-sky-500 w-5 h-5",
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -23,7 +23,7 @@ export const styles: StylesConfig = {
|
||||||
...styles,
|
...styles,
|
||||||
width: "15rem",
|
width: "15rem",
|
||||||
border: "1px solid #e0f2fe",
|
border: "1px solid #e0f2fe",
|
||||||
borderRadius: "0.25rem",
|
borderRadius: "0.375rem",
|
||||||
fontSize: "0.875rem",
|
fontSize: "0.875rem",
|
||||||
lineHeight: "1.25rem",
|
lineHeight: "1.25rem",
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -35,16 +35,32 @@ export default function ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border border-sky-100 mb-5 bg-gray-100 p-5 rounded flex items-center gap-5 group/item">
|
<div className="mx-auto border border-sky-100 mb-5 bg-gray-100 p-2 rounded-md flex items-start relative gap-5 group/item">
|
||||||
<Image
|
<Image
|
||||||
src={`http://icons.duckduckgo.com/ip3/${shortendURL}.ico`}
|
src={`http://icons.duckduckgo.com/ip3/${shortendURL}.ico`}
|
||||||
width={100}
|
width={32}
|
||||||
height={100}
|
height={32}
|
||||||
alt=""
|
alt=""
|
||||||
className="blur-sm opacity-80 group-hover/item:opacity-100 duration-100"
|
className="opacity-100 duration-100 select-none mt-3"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
|
onError={(e) => {
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
target.style.opacity = "0";
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-between gap-5 w-full">
|
<Image
|
||||||
|
src={`http://icons.duckduckgo.com/ip3/${shortendURL}.ico`}
|
||||||
|
width={80}
|
||||||
|
height={80}
|
||||||
|
alt=""
|
||||||
|
className="blur-sm absolute left-0 opacity-50 select-none"
|
||||||
|
draggable="false"
|
||||||
|
onError={(e) => {
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
target.style.opacity = "0";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="flex justify-between gap-5 w-full z-0">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-baseline gap-1">
|
<div className="flex items-baseline gap-1">
|
||||||
<p className="text-sm text-sky-300 font-bold">{count + 1}.</p>
|
<p className="text-sm text-sky-300 font-bold">{count + 1}.</p>
|
||||||
|
@ -87,7 +103,8 @@ export default function ({
|
||||||
<div className="flex flex-col justify-between items-end relative">
|
<div className="flex flex-col justify-between items-end relative">
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={faEllipsis}
|
icon={faEllipsis}
|
||||||
className="w-6 h-6 text-gray-500 rounded cursor-pointer hover:bg-white hover:outline outline-sky-100 outline-1 duration-100 p-2"
|
title="More"
|
||||||
|
className="w-6 h-6 text-gray-500 rounded-md cursor-pointer hover:bg-white hover:outline outline-sky-100 outline-1 duration-100 p-1"
|
||||||
onClick={() => setEditDropdown(!editDropdown)}
|
onClick={() => setEditDropdown(!editDropdown)}
|
||||||
id="edit-dropdown"
|
id="edit-dropdown"
|
||||||
/>
|
/>
|
||||||
|
@ -153,7 +170,7 @@ export default function ({
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
if (target.id !== "edit-dropdown") setEditDropdown(false);
|
if (target.id !== "edit-dropdown") setEditDropdown(false);
|
||||||
}}
|
}}
|
||||||
className="absolute top-10 right-0"
|
className="absolute top-8 right-0"
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -65,22 +65,38 @@ export default function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between items-center p-5 border-solid border-b-sky-100 border border-l-white">
|
<div className="flex justify-between items-center p-2 border-solid border-b-sky-100 border-b">
|
||||||
<div className="text-sky-900 rounded my-1 flex items-center gap-2 font-bold">
|
<div className="text-sky-900 rounded-md my-1 flex items-center gap-2 font-bold">
|
||||||
{pageIcon ? (
|
{pageIcon ? (
|
||||||
<FontAwesomeIcon icon={pageIcon} className="w-4 text-sky-300" />
|
<FontAwesomeIcon icon={pageIcon} className="w-4 text-sky-300" />
|
||||||
) : null}
|
) : null}
|
||||||
<p>{pageName}</p>
|
<p>{pageName}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
|
<div className="flex items-center gap-2 justify-between">
|
||||||
|
<div className="flex items-center relative">
|
||||||
|
<label
|
||||||
|
htmlFor="search-box"
|
||||||
|
className="inline-flex w-fit absolute right-0 cursor-pointer"
|
||||||
|
title="Search"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faMagnifyingGlass}
|
||||||
|
className="select-none w-5 h-5 rounded-md p-1 text-sky-500 "
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="search-box"
|
||||||
|
type="text"
|
||||||
|
placeholder="Search for Links"
|
||||||
|
className="border border-sky-100 rounded-md pr-6 w-6 focus:border-sky-500 focus:w-60 hover:border-sky-500 duration-100 outline-none p-1 text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={faPlus}
|
icon={faPlus}
|
||||||
onClick={toggleLinkModal}
|
onClick={toggleLinkModal}
|
||||||
className="select-none cursor-pointer w-5 h-5 text-white bg-sky-500 p-2 rounded hover:bg-sky-400 duration-100"
|
title="New Link"
|
||||||
/>
|
className="select-none cursor-pointer w-5 h-5 text-sky-500 p-1 rounded-md hover:outline-sky-500 outline duration-100 hover:bg-white outline-sky-100 outline-1"
|
||||||
<FontAwesomeIcon
|
|
||||||
icon={faMagnifyingGlass}
|
|
||||||
className="select-none cursor-pointer w-5 h-5 text-white bg-sky-500 p-2 rounded hover:bg-sky-400 duration-100"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{linkModal ? (
|
{linkModal ? (
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import React, { ReactElement } from "react";
|
import React, { ReactElement } from "react";
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ interface SidebarItemProps {
|
||||||
export default function ({ text, icon, path }: SidebarItemProps) {
|
export default function ({ text, icon, path }: SidebarItemProps) {
|
||||||
return (
|
return (
|
||||||
<Link href={path}>
|
<Link href={path}>
|
||||||
<div className="hover:bg-gray-50 hover:outline outline-sky-100 outline-1 duration-100 rounded my-1 p-3 cursor-pointer flex items-center gap-2">
|
<div className="hover:bg-gray-50 hover:outline outline-sky-100 outline-1 duration-100 rounded-md my-1 p-2 cursor-pointer flex items-center gap-2">
|
||||||
{React.cloneElement(icon, {
|
{React.cloneElement(icon, {
|
||||||
className: "w-4 text-sky-300",
|
className: "w-4 text-sky-300",
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -48,10 +48,10 @@ export default function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed bg-gray-100 top-0 bottom-0 left-0 w-80 p-5 overflow-y-auto hide-scrollbar border-solid border-r-sky-100 border z-10">
|
<div className="fixed bg-gray-100 top-0 bottom-0 left-0 w-80 p-2 overflow-y-auto hide-scrollbar border-solid border-r-sky-100 border z-10">
|
||||||
<div className="relative w-fit">
|
<div className="relative w-fit">
|
||||||
<div
|
<div
|
||||||
className="flex gap-2 items-center mb-5 p-3 w-fit text-gray-600 cursor-pointer hover:outline outline-sky-100 outline-1 hover:bg-gray-50 rounded duration-100"
|
className="flex gap-2 items-center mb-5 p-2 w-fit text-gray-600 cursor-pointer hover:outline outline-sky-100 outline-1 hover:bg-gray-50 rounded-md duration-100"
|
||||||
onClick={() => setProfileDropdown(!profileDropdown)}
|
onClick={() => setProfileDropdown(!profileDropdown)}
|
||||||
id="profile-dropdown"
|
id="profile-dropdown"
|
||||||
>
|
>
|
||||||
|
@ -84,27 +84,27 @@ export default function () {
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
if (target.id !== "profile-dropdown") setProfileDropdown(false);
|
if (target.id !== "profile-dropdown") setProfileDropdown(false);
|
||||||
}}
|
}}
|
||||||
className="absolute top-12 left-0"
|
className="absolute top-10 left-0"
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Link href="links">
|
<Link href="links">
|
||||||
<div className="hover:bg-gray-50 hover:outline outline-sky-100 outline-1 duration-100 text-sky-900 rounded my-1 p-3 cursor-pointer flex items-center gap-2">
|
<div className="hover:bg-gray-50 hover:outline outline-sky-100 outline-1 duration-100 text-sky-900 rounded-md my-1 p-2 cursor-pointer flex items-center gap-2">
|
||||||
<FontAwesomeIcon icon={faBookmark} className="w-4 text-sky-300" />
|
<FontAwesomeIcon icon={faBookmark} className="w-4 text-sky-300" />
|
||||||
<p>All Links</p>
|
<p>All Links</p>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link href="/collections">
|
<Link href="/collections">
|
||||||
<div className="hover:bg-gray-50 hover:outline outline-sky-100 outline-1 duration-100 text-sky-900 rounded my-1 p-3 cursor-pointer flex items-center gap-2">
|
<div className="hover:bg-gray-50 hover:outline outline-sky-100 outline-1 duration-100 text-sky-900 rounded-md my-1 p-2 cursor-pointer flex items-center gap-2">
|
||||||
<FontAwesomeIcon icon={faBox} className="w-4 text-sky-300" />
|
<FontAwesomeIcon icon={faBox} className="w-4 text-sky-300" />
|
||||||
<p>All Collections</p>
|
<p>All Collections</p>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<div className="text-gray-500 flex items-center justify-between mt-5">
|
<div className="text-gray-500 flex items-center justify-between mt-5">
|
||||||
<p className="text-sm p-3">Collections</p>
|
<p className="text-sm p-2">Collections</p>
|
||||||
{collectionInput ? (
|
{collectionInput ? (
|
||||||
<ClickAwayHandler
|
<ClickAwayHandler
|
||||||
onClickOutside={toggleCollectionInput}
|
onClickOutside={toggleCollectionInput}
|
||||||
|
@ -113,7 +113,7 @@ export default function () {
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Enter Collection Name"
|
placeholder="Enter Collection Name"
|
||||||
className="w-44 rounded p-2 border-sky-100 border-solid border text-sm outline-none"
|
className="w-44 rounded-md p-1 border-sky-500 border-solid border text-sm outline-none"
|
||||||
onKeyDown={submitCollection}
|
onKeyDown={submitCollection}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
|
@ -122,7 +122,8 @@ export default function () {
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={faPlus}
|
icon={faPlus}
|
||||||
onClick={toggleCollectionInput}
|
onClick={toggleCollectionInput}
|
||||||
className="select-none cursor-pointer p-2 w-3"
|
title="Add Collection"
|
||||||
|
className="select-none text-gray-500 rounded-md cursor-pointer hover:bg-white hover:outline outline-sky-100 outline-1 duration-100 p-1 w-3"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -139,7 +140,7 @@ export default function () {
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-500 flex items-center justify-between mt-5">
|
<div className="text-gray-500 flex items-center justify-between mt-5">
|
||||||
<p className="text-sm p-3">Tags</p>
|
<p className="text-sm p-2">Tags</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{tags.map((e, i) => {
|
{tags.map((e, i) => {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { chromium, devices } from "playwright";
|
import { chromium, devices } from "playwright";
|
||||||
|
import { prisma } from "@/lib/api/db";
|
||||||
|
|
||||||
export default async (url: string, collectionId: number, linkId: number) => {
|
export default async (url: string, collectionId: number, linkId: number) => {
|
||||||
const archivePath = `data/archives/${collectionId}/${linkId}`;
|
const archivePath = `data/archives/${collectionId}/${linkId}`;
|
||||||
|
@ -12,9 +13,18 @@ export default async (url: string, collectionId: number, linkId: number) => {
|
||||||
|
|
||||||
await page.goto(url);
|
await page.goto(url);
|
||||||
|
|
||||||
await page.pdf({ path: archivePath + ".pdf" });
|
const linkExists = await prisma.link.findFirst({
|
||||||
|
where: {
|
||||||
|
id: linkId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await page.screenshot({ fullPage: true, path: archivePath + ".png" });
|
if (linkExists) {
|
||||||
|
await Promise.all([
|
||||||
|
page.pdf({ path: archivePath + ".pdf" }),
|
||||||
|
page.screenshot({ fullPage: true, path: archivePath + ".png" }),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
await context.close();
|
await context.close();
|
||||||
await browser.close();
|
await browser.close();
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { prisma } from "@/lib/api/db";
|
import { prisma } from "@/lib/api/db";
|
||||||
import { Session } from "next-auth";
|
import { Session } from "next-auth";
|
||||||
import { ExtendedLink, NewLink } from "@/types/global";
|
import { ExtendedLink } from "@/types/global";
|
||||||
import { existsSync, mkdirSync } from "fs";
|
import fs from "fs";
|
||||||
import getTitle from "../../getTitle";
|
|
||||||
import archive from "../../archive";
|
|
||||||
import { Link, UsersAndCollections } from "@prisma/client";
|
import { Link, UsersAndCollections } from "@prisma/client";
|
||||||
import AES from "crypto-js/aes";
|
|
||||||
import hasAccessToCollection from "@/lib/api/hasAccessToCollection";
|
import hasAccessToCollection from "@/lib/api/hasAccessToCollection";
|
||||||
|
|
||||||
export default async function (
|
export default async function (
|
||||||
|
@ -42,6 +39,14 @@ export default async function (
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fs.unlink(`data/archives/${link.collectionId}/${link.id}.pdf`, (err) => {
|
||||||
|
if (err) console.log(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.unlink(`data/archives/${link.collectionId}/${link.id}.png`, (err) => {
|
||||||
|
if (err) console.log(err);
|
||||||
|
});
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
response: deleteLink,
|
response: deleteLink,
|
||||||
});
|
});
|
||||||
|
|
|
@ -118,7 +118,7 @@ export default async function (
|
||||||
|
|
||||||
const AES_SECRET = process.env.AES_SECRET as string;
|
const AES_SECRET = process.env.AES_SECRET as string;
|
||||||
|
|
||||||
const screenShotHashedPath = AES.encrypt(
|
const screenshotHashedPath = AES.encrypt(
|
||||||
`data/archives/${newLink.collectionId}/${newLink.id}.png`,
|
`data/archives/${newLink.collectionId}/${newLink.id}.png`,
|
||||||
AES_SECRET
|
AES_SECRET
|
||||||
).toString();
|
).toString();
|
||||||
|
@ -130,7 +130,7 @@ export default async function (
|
||||||
|
|
||||||
const updatedLink: ExtendedLink = await prisma.link.update({
|
const updatedLink: ExtendedLink = await prisma.link.update({
|
||||||
where: { id: newLink.id },
|
where: { id: newLink.id },
|
||||||
data: { screenshotPath: screenShotHashedPath, pdfPath: pdfHashedPath },
|
data: { screenshotPath: screenshotHashedPath, pdfPath: pdfHashedPath },
|
||||||
include: { tags: true, collection: true },
|
include: { tags: true, collection: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,15 @@ export default async function (
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
session: Session
|
session: Session
|
||||||
) {
|
) {
|
||||||
|
// tag cleanup
|
||||||
|
await prisma.tag.deleteMany({
|
||||||
|
where: {
|
||||||
|
links: {
|
||||||
|
none: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const tags = await prisma.tag.findMany({
|
const tags = await prisma.tag.findMany({
|
||||||
where: {
|
where: {
|
||||||
collections: {
|
collections: {
|
||||||
|
|
|
@ -12,8 +12,8 @@ export default function () {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// ml-80
|
// ml-80
|
||||||
<div className="p-5">
|
<div className="p-2">
|
||||||
<p className="text-center mb-5 text-gray-500 font-bold text-sm">
|
<p className="text-right mb-2 text-gray-500 font-bold text-sm">
|
||||||
{linksByCollection.length || 0} Links Found
|
{linksByCollection.length || 0} Links Found
|
||||||
</p>
|
</p>
|
||||||
{linksByCollection.map((e, i) => {
|
{linksByCollection.map((e, i) => {
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default function () {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// ml-80
|
// ml-80
|
||||||
<div className="flex flex-wrap p-5">
|
<div className="flex flex-wrap p-2 gap-2">
|
||||||
{collections.map((e, i) => {
|
{collections.map((e, i) => {
|
||||||
return <CollectionCard key={i} collection={e} />;
|
return <CollectionCard key={i} collection={e} />;
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -42,17 +42,17 @@ export default function () {
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
value={form.email}
|
value={form.email}
|
||||||
onChange={(e) => setForm({ ...form, email: e.target.value })}
|
onChange={(e) => setForm({ ...form, email: e.target.value })}
|
||||||
className="border border-gray-700 rounded block m-2 mx-auto p-2"
|
className="border border-gray-700 rounded-md block m-2 mx-auto p-2"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
value={form.password}
|
value={form.password}
|
||||||
onChange={(e) => setForm({ ...form, password: e.target.value })}
|
onChange={(e) => setForm({ ...form, password: e.target.value })}
|
||||||
className="border border-gray-700 rounded block m-2 mx-auto p-2"
|
className="border border-gray-700 rounded-md block m-2 mx-auto p-2"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="mx-auto bg-black w-min p-3 m-5 text-white rounded cursor-pointer"
|
className="mx-auto bg-black w-min p-3 m-5 text-white rounded-md cursor-pointer"
|
||||||
onClick={loginUser}
|
onClick={loginUser}
|
||||||
>
|
>
|
||||||
Login
|
Login
|
||||||
|
|
|
@ -57,24 +57,24 @@ export default function () {
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
value={form.name}
|
value={form.name}
|
||||||
onChange={(e) => setForm({ ...form, name: e.target.value })}
|
onChange={(e) => setForm({ ...form, name: e.target.value })}
|
||||||
className="border border-gray-700 rounded block m-2 mx-auto p-2"
|
className="border border-gray-700 rounded-md block m-2 mx-auto p-2"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
value={form.email}
|
value={form.email}
|
||||||
onChange={(e) => setForm({ ...form, email: e.target.value })}
|
onChange={(e) => setForm({ ...form, email: e.target.value })}
|
||||||
className="border border-gray-700 rounded block m-2 mx-auto p-2"
|
className="border border-gray-700 rounded-md block m-2 mx-auto p-2"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
value={form.password}
|
value={form.password}
|
||||||
onChange={(e) => setForm({ ...form, password: e.target.value })}
|
onChange={(e) => setForm({ ...form, password: e.target.value })}
|
||||||
className="border border-gray-700 rounded block m-2 mx-auto p-2"
|
className="border border-gray-700 rounded-md block m-2 mx-auto p-2"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="mx-auto bg-black w-min p-3 m-5 text-white rounded cursor-pointer"
|
className="mx-auto bg-black w-min p-3 m-5 text-white rounded-md cursor-pointer"
|
||||||
onClick={registerUser}
|
onClick={registerUser}
|
||||||
>
|
>
|
||||||
Register
|
Register
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { ExtendedLink, NewLink } from "@/types/global";
|
import { ExtendedLink, NewLink } from "@/types/global";
|
||||||
|
import useTagStore from "./tags";
|
||||||
|
import useCollectionStore from "./collections";
|
||||||
|
|
||||||
type LinkStore = {
|
type LinkStore = {
|
||||||
links: ExtendedLink[];
|
links: ExtendedLink[];
|
||||||
|
@ -34,6 +36,9 @@ const useLinkStore = create<LinkStore>()((set) => ({
|
||||||
links: [...state.links, data.response],
|
links: [...state.links, data.response],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
useTagStore.getState().setTags();
|
||||||
|
useCollectionStore.getState().setCollections();
|
||||||
|
|
||||||
return response.ok;
|
return response.ok;
|
||||||
},
|
},
|
||||||
updateLink: (link) =>
|
updateLink: (link) =>
|
||||||
|
@ -56,7 +61,7 @@ const useLinkStore = create<LinkStore>()((set) => ({
|
||||||
links: state.links.filter((e) => e.id !== link.id),
|
links: state.links.filter((e) => e.id !== link.id),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
console.log(data);
|
useTagStore.getState().setTags();
|
||||||
|
|
||||||
return response.ok;
|
return response.ok;
|
||||||
},
|
},
|
||||||
|
|
Ŝarĝante…
Reference in New Issue