finalized dashboard
This commit is contained in:
parent
41446f5bd4
commit
99cfbdf44b
|
@ -15,6 +15,7 @@ import Dropdown from "./Dropdown";
|
|||
import useLinkStore from "@/store/links";
|
||||
import Link from "next/link";
|
||||
import useCollectionStore from "@/store/collections";
|
||||
import useAccountStore from "@/store/account";
|
||||
import useModalStore from "@/store/modals";
|
||||
|
||||
type Props = {
|
||||
|
@ -30,6 +31,8 @@ export default function LinkCard({ link, count, className }: Props) {
|
|||
|
||||
const { collections } = useCollectionStore();
|
||||
|
||||
const { account } = useAccountStore();
|
||||
|
||||
const [collection, setCollection] = useState<CollectionIncludingMembers>(
|
||||
collections.find(
|
||||
(e) => e.id === link.collection.id
|
||||
|
@ -44,7 +47,7 @@ export default function LinkCard({ link, count, className }: Props) {
|
|||
);
|
||||
}, [collections]);
|
||||
|
||||
const { removeLink } = useLinkStore();
|
||||
const { removeLink, updateLink } = useLinkStore();
|
||||
|
||||
const url = new URL(link.url);
|
||||
const formattedDate = new Date(link.createdAt as string).toLocaleString(
|
||||
|
@ -66,7 +69,7 @@ export default function LinkCard({ link, count, className }: Props) {
|
|||
width={42}
|
||||
height={42}
|
||||
alt=""
|
||||
className="select-none mt-3 z-10 rounded-full shadow border-[3px] border-white bg-white"
|
||||
className="select-none mt-3 z-10 rounded-full shadow border-[3px] border-white bg-white aspect-square"
|
||||
draggable="false"
|
||||
onError={(e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
|
@ -129,7 +132,7 @@ export default function LinkCard({ link, count, className }: Props) {
|
|||
className="group/url"
|
||||
>
|
||||
<div className="text-sky-400 font-bold flex items-center gap-1">
|
||||
<p className="truncate w-40">{url.host}</p>
|
||||
<p className="truncate max-w-[10rem]">{url.host}</p>
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowUpRightFromSquare}
|
||||
className="w-3 opacity-0 group-hover/url:opacity-100 duration-75"
|
||||
|
@ -182,6 +185,22 @@ export default function LinkCard({ link, count, className }: Props) {
|
|||
{expandDropdown ? (
|
||||
<Dropdown
|
||||
items={[
|
||||
{
|
||||
name:
|
||||
link?.pinnedBy && link.pinnedBy[0]
|
||||
? "Unpin"
|
||||
: "Pin to Dashboard",
|
||||
onClick: () => {
|
||||
updateLink({
|
||||
...link,
|
||||
pinnedBy:
|
||||
link?.pinnedBy && link.pinnedBy[0]
|
||||
? undefined
|
||||
: [{ id: account.id }],
|
||||
});
|
||||
setExpandDropdown(false);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Edit",
|
||||
onClick: () => {
|
||||
|
|
|
@ -37,8 +37,6 @@ export default function EditLink({
|
|||
name: "",
|
||||
url: "",
|
||||
title: "",
|
||||
screenshotPath: "",
|
||||
pdfPath: "",
|
||||
tags: [],
|
||||
collection: {
|
||||
name: "",
|
||||
|
|
|
@ -33,9 +33,9 @@ export default function ProfilePhoto({
|
|||
|
||||
return error || !src ? (
|
||||
<div
|
||||
className={`bg-sky-500 text-white h-10 w-10 shadow rounded-full border-[3px] border-slate-200 flex items-center justify-center ${className}`}
|
||||
className={`bg-sky-500 text-white h-10 w-10 aspect-square shadow rounded-full border-[3px] border-slate-200 flex items-center justify-center ${className}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faUser} className="w-1/2 h-1/2" />
|
||||
<FontAwesomeIcon icon={faUser} className="w-1/2 h-1/2 aspect-square" />
|
||||
</div>
|
||||
) : (
|
||||
<Image
|
||||
|
@ -43,7 +43,7 @@ export default function ProfilePhoto({
|
|||
src={src}
|
||||
height={112}
|
||||
width={112}
|
||||
className={`h-10 w-10 shadow rounded-full border-[3px] border-slate-200 ${className}`}
|
||||
className={`h-10 w-10 shadow rounded-full aspect-square border-[3px] border-slate-200 ${className}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import Image from "next/image";
|
|||
import { Link as LinkType } from "@prisma/client";
|
||||
|
||||
type Props = {
|
||||
link: Omit<LinkType, "screenshotPath" | "pdfPath">;
|
||||
link: LinkType;
|
||||
count: number;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ export default async function getLink(userId: number) {
|
|||
include: {
|
||||
tags: true,
|
||||
collection: true,
|
||||
pinnedBy: {
|
||||
where: { id: userId },
|
||||
select: { id: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -64,10 +64,18 @@ export default async function updateLink(
|
|||
},
|
||||
})),
|
||||
},
|
||||
pinnedBy:
|
||||
link?.pinnedBy && link.pinnedBy[0]
|
||||
? { connect: { id: userId } }
|
||||
: { disconnect: { id: userId } },
|
||||
},
|
||||
include: {
|
||||
tags: true,
|
||||
collection: true,
|
||||
pinnedBy: {
|
||||
where: { id: userId },
|
||||
select: { id: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ export default function Dashboard() {
|
|||
|
||||
<div className="flex flex-col 2xl:flex-row items-start justify-evenly 2xl:gap-2">
|
||||
<Disclosure defaultOpen={linkPinDisclosure}>
|
||||
<div className="flex flex-col gap-5 p-2 w-full">
|
||||
<div className="flex flex-col gap-5 p-2 w-full mx-auto md:w-2/3">
|
||||
<Disclosure.Button
|
||||
onClick={() => {
|
||||
setLinkPinDisclosure(!linkPinDisclosure);
|
||||
|
@ -131,15 +131,17 @@ export default function Dashboard() {
|
|||
leaveTo="transform opacity-0 -translate-y-3"
|
||||
>
|
||||
<Disclosure.Panel className="flex flex-col gap-5 w-full">
|
||||
{links.slice(0, 5).map((e, i) => (
|
||||
<LinkCard key={i} link={e} count={i} />
|
||||
))}
|
||||
{links
|
||||
.filter((e) => e.pinnedBy && e.pinnedBy[0])
|
||||
.map((e, i) => (
|
||||
<LinkCard key={i} link={e} count={i} />
|
||||
))}
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
</Disclosure>
|
||||
|
||||
<Disclosure defaultOpen={collectionPinDisclosure}>
|
||||
{/* <Disclosure defaultOpen={collectionPinDisclosure}>
|
||||
<div className="flex flex-col gap-5 p-2 w-full">
|
||||
<Disclosure.Button
|
||||
onClick={() => {
|
||||
|
@ -174,9 +176,9 @@ export default function Dashboard() {
|
|||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
</Disclosure>
|
||||
</Disclosure> */}
|
||||
|
||||
<Disclosure defaultOpen={tagPinDisclosure}>
|
||||
{/* <Disclosure defaultOpen={tagPinDisclosure}>
|
||||
<div className="flex flex-col gap-5 p-2 w-full">
|
||||
<Disclosure.Button
|
||||
onClick={() => {
|
||||
|
@ -217,7 +219,7 @@ export default function Dashboard() {
|
|||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
</Disclosure>
|
||||
</Disclosure> */}
|
||||
</div>
|
||||
</div>
|
||||
</MainLayout>
|
||||
|
|
|
@ -24,33 +24,6 @@ CREATE TABLE "Collection" (
|
|||
CONSTRAINT "Collection_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PinnedCollections" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"collectionId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "PinnedCollections_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PinnedLinks" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"linkId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "PinnedLinks_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PinnedTags" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"tagId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "PinnedTags_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "UsersAndCollections" (
|
||||
"userId" INTEGER NOT NULL,
|
||||
|
@ -83,6 +56,12 @@ CREATE TABLE "Tag" (
|
|||
CONSTRAINT "Tag_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_LinkToUser" (
|
||||
"A" INTEGER NOT NULL,
|
||||
"B" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_LinkToTag" (
|
||||
"A" INTEGER NOT NULL,
|
||||
|
@ -98,6 +77,12 @@ CREATE UNIQUE INDEX "Collection_name_ownerId_key" ON "Collection"("name", "owner
|
|||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Tag_name_ownerId_key" ON "Tag"("name", "ownerId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "_LinkToUser_AB_unique" ON "_LinkToUser"("A", "B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_LinkToUser_B_index" ON "_LinkToUser"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "_LinkToTag_AB_unique" ON "_LinkToTag"("A", "B");
|
||||
|
||||
|
@ -107,24 +92,6 @@ CREATE INDEX "_LinkToTag_B_index" ON "_LinkToTag"("B");
|
|||
-- AddForeignKey
|
||||
ALTER TABLE "Collection" ADD CONSTRAINT "Collection_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PinnedCollections" ADD CONSTRAINT "PinnedCollections_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PinnedCollections" ADD CONSTRAINT "PinnedCollections_collectionId_fkey" FOREIGN KEY ("collectionId") REFERENCES "Collection"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PinnedLinks" ADD CONSTRAINT "PinnedLinks_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PinnedLinks" ADD CONSTRAINT "PinnedLinks_linkId_fkey" FOREIGN KEY ("linkId") REFERENCES "Link"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PinnedTags" ADD CONSTRAINT "PinnedTags_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PinnedTags" ADD CONSTRAINT "PinnedTags_tagId_fkey" FOREIGN KEY ("tagId") REFERENCES "Tag"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "UsersAndCollections" ADD CONSTRAINT "UsersAndCollections_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
|
@ -137,6 +104,12 @@ ALTER TABLE "Link" ADD CONSTRAINT "Link_collectionId_fkey" FOREIGN KEY ("collect
|
|||
-- AddForeignKey
|
||||
ALTER TABLE "Tag" ADD CONSTRAINT "Tag_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_LinkToUser" ADD CONSTRAINT "_LinkToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "Link"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_LinkToUser" ADD CONSTRAINT "_LinkToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_LinkToTag" ADD CONSTRAINT "_LinkToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Link"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
|
@ -14,9 +14,9 @@ model User {
|
|||
password String
|
||||
collections Collection[]
|
||||
tags Tag[]
|
||||
pinnedCollections PinnedCollections[]
|
||||
pinnedLinks PinnedLinks[]
|
||||
pinnedTags PinnedTags[]
|
||||
|
||||
pinnedLinks Link[]
|
||||
|
||||
collectionsJoined UsersAndCollections[]
|
||||
isPrivate Boolean @default(false)
|
||||
whitelistedUsers String[] @default([])
|
||||
|
@ -29,7 +29,8 @@ model Collection {
|
|||
description String @default("")
|
||||
color String @default("#0ea5e9")
|
||||
isPublic Boolean @default(false)
|
||||
pins PinnedCollections[]
|
||||
|
||||
|
||||
owner User @relation(fields: [ownerId], references: [id])
|
||||
ownerId Int
|
||||
members UsersAndCollections[]
|
||||
|
@ -39,37 +40,6 @@ model Collection {
|
|||
@@unique([name, ownerId])
|
||||
}
|
||||
|
||||
model PinnedCollections {
|
||||
id Int @id @default(autoincrement())
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
||||
collection Collection @relation(fields: [collectionId], references: [id])
|
||||
collectionId Int
|
||||
}
|
||||
|
||||
model PinnedLinks {
|
||||
id Int @id @default(autoincrement())
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
||||
link Link @relation(fields: [linkId], references: [id])
|
||||
linkId Int
|
||||
}
|
||||
|
||||
model PinnedTags {
|
||||
id Int @id @default(autoincrement())
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
||||
tag Tag @relation(fields: [tagId], references: [id])
|
||||
tagId Int
|
||||
}
|
||||
|
||||
|
||||
model UsersAndCollections {
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
@ -89,10 +59,12 @@ model Link {
|
|||
name String
|
||||
url String
|
||||
title String
|
||||
|
||||
pinnedBy User[]
|
||||
|
||||
collection Collection @relation(fields: [collectionId], references: [id])
|
||||
collectionId Int
|
||||
tags Tag[]
|
||||
pins PinnedLinks[]
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
|
@ -100,7 +72,6 @@ model Tag {
|
|||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
links Link[]
|
||||
pins PinnedTags[]
|
||||
owner User @relation(fields: [ownerId], references: [id])
|
||||
ownerId Int
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ export interface LinkIncludingCollectionAndTags
|
|||
createdAt?: string;
|
||||
collectionId?: number;
|
||||
tags: Tag[];
|
||||
pinnedBy?: {
|
||||
id: number;
|
||||
}[];
|
||||
collection: OptionalExcluding<Collection, "name" | "ownerId">;
|
||||
}
|
||||
|
||||
|
@ -37,5 +40,5 @@ export interface AccountSettings extends User {
|
|||
export interface PublicCollectionIncludingLinks
|
||||
extends Omit<Collection, "ownerId"> {
|
||||
ownerName?: string;
|
||||
links: Omit<Link, "screenshotPath" | "pdfPath">[];
|
||||
links: Link[];
|
||||
}
|
||||
|
|
Ŝarĝante…
Reference in New Issue