Many changes.
This commit is contained in:
parent
d19204f4c0
commit
e0f4c71eb2
|
@ -3,6 +3,7 @@ import React, { useRef, useEffect, ReactNode, RefObject } from "react";
|
||||||
interface Props {
|
interface Props {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
onClickOutside: Function;
|
onClickOutside: Function;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useOutsideAlerter(
|
function useOutsideAlerter(
|
||||||
|
@ -27,9 +28,17 @@ function useOutsideAlerter(
|
||||||
}, [ref, onClickOutside]);
|
}, [ref, onClickOutside]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function OutsideAlerter({ children, onClickOutside }: Props) {
|
export default function OutsideAlerter({
|
||||||
|
children,
|
||||||
|
onClickOutside,
|
||||||
|
className,
|
||||||
|
}: Props) {
|
||||||
const wrapperRef = useRef(null);
|
const wrapperRef = useRef(null);
|
||||||
useOutsideAlerter(wrapperRef, onClickOutside);
|
useOutsideAlerter(wrapperRef, onClickOutside);
|
||||||
|
|
||||||
return <div ref={wrapperRef}>{children}</div>;
|
return (
|
||||||
|
<div ref={wrapperRef} className={className}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import useCollectionSlice from "@/store/collection";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { faChevronRight } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
|
export default function Collections() {
|
||||||
|
const { collections } = useCollectionSlice();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-wrap">
|
||||||
|
{collections.map((e, i) => {
|
||||||
|
const formattedDate = new Date(e.createdAt).toLocaleString("en-US", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<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:shadow duration-100"
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<div className="flex justify-between text-sky-900">
|
||||||
|
<p className="text-lg w-max">{e.name}</p>
|
||||||
|
<FontAwesomeIcon icon={faChevronRight} className="w-3" />
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-sky-300">{formattedDate}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,28 +0,0 @@
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
interface Collections {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
createdAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Collections() {
|
|
||||||
const [collections, setCollections] = useState<Collections[]>([]);
|
|
||||||
useEffect(() => {
|
|
||||||
fetch("/api/routes/collections/getCollections")
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => setCollections(data.response));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-wrap">
|
|
||||||
{collections.map((e, i) => {
|
|
||||||
return (
|
|
||||||
<div className="p-5 bg-gray-200 m-2 w-max rounded" key={i}>
|
|
||||||
<p>{e.name}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@ import { signOut } from "next-auth/react";
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between p-5">
|
<div className="flex justify-between p-5 border-solid border-b-sky-100 border border-l-white">
|
||||||
<p>Navbar</p>
|
<p>Navbar</p>
|
||||||
<div onClick={() => signOut()} className="cursor-pointer w-max">
|
<div onClick={() => signOut()} className="cursor-pointer w-max">
|
||||||
Sign Out
|
Sign Out
|
||||||
|
|
|
@ -1,16 +1,26 @@
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import ClickAwayHandler from "@/components/ClickAwayHandler";
|
import ClickAwayHandler from "@/components/ClickAwayHandler";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import useCollectionSlice from "@/store/collection";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { faFolder, faUserCircle } from "@fortawesome/free-regular-svg-icons";
|
||||||
|
import {
|
||||||
|
faDatabase,
|
||||||
|
faPlus,
|
||||||
|
faChevronDown,
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
export default function Sidebar() {
|
export default function Sidebar() {
|
||||||
const { data: session, status } = useSession();
|
const { data: session } = useSession();
|
||||||
|
|
||||||
const [addCollection, setAddCollection] = useState(false);
|
const [collectionInput, setCollectionInput] = useState(false);
|
||||||
|
|
||||||
|
const { collections, addCollection } = useCollectionSlice();
|
||||||
|
|
||||||
const user = session?.user;
|
const user = session?.user;
|
||||||
|
|
||||||
const toggleAddCollection = () => {
|
const toggleCollectionInput = () => {
|
||||||
setAddCollection(!addCollection);
|
setCollectionInput(!collectionInput);
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitCollection = async (
|
const submitCollection = async (
|
||||||
|
@ -19,42 +29,62 @@ export default function Sidebar() {
|
||||||
const collectionName: string = (event.target as HTMLInputElement).value;
|
const collectionName: string = (event.target as HTMLInputElement).value;
|
||||||
|
|
||||||
if (event.key === "Enter" && collectionName) {
|
if (event.key === "Enter" && collectionName) {
|
||||||
await fetch("/api/routes/collections/postCollection", {
|
addCollection(collectionName);
|
||||||
body: JSON.stringify({ collectionName }),
|
(event.target as HTMLInputElement).value = "";
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
method: "POST",
|
|
||||||
})
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => console.log(data));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed bg-gray-200 top-0 bottom-0 left-0 w-80 p-5">
|
<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">
|
||||||
<div className="flex justify-between gap-5 items-center h-9">
|
<div className="flex gap-3 items-center mb-5 cursor-pointer w-fit text-gray-600">
|
||||||
|
<FontAwesomeIcon icon={faUserCircle} className="h-8" />
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
<p>{user?.name}</p>
|
<p>{user?.name}</p>
|
||||||
|
<FontAwesomeIcon icon={faChevronDown} className="h-3" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{addCollection ? (
|
<div className="hover:bg-sky-100 hover:shadow-sm duration-100 text-sky-900 rounded my-1 p-3 cursor-pointer flex items-center gap-2">
|
||||||
<ClickAwayHandler onClickOutside={toggleAddCollection}>
|
<FontAwesomeIcon icon={faDatabase} className="w-4" />
|
||||||
|
<p>All Collections</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-gray-500 flex items-center justify-between mt-5">
|
||||||
|
<p>Collections</p>
|
||||||
|
{collectionInput ? (
|
||||||
|
<ClickAwayHandler
|
||||||
|
onClickOutside={toggleCollectionInput}
|
||||||
|
className="w-fit"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Enter Collection Name"
|
placeholder="Enter Collection Name"
|
||||||
className="w-48 rounded p-2"
|
className="w-44 rounded p-1"
|
||||||
onKeyDown={submitCollection}
|
onKeyDown={submitCollection}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</ClickAwayHandler>
|
</ClickAwayHandler>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<FontAwesomeIcon
|
||||||
onClick={toggleAddCollection}
|
icon={faPlus}
|
||||||
className="select-none cursor-pointer bg-white rounded p-2"
|
onClick={toggleCollectionInput}
|
||||||
>
|
className="select-none cursor-pointer rounded p-2 w-3"
|
||||||
Create Collection +
|
/>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
{collections.map((e, i) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="hover:bg-sky-100 hover:shadow-sm duration-100 text-sky-900 rounded my-1 p-3 cursor-pointer flex items-center gap-2"
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faFolder} className="w-4" />
|
||||||
|
<p>{e.name}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { useSession } from "next-auth/react";
|
||||||
import Loader from "../components/Loader";
|
import Loader from "../components/Loader";
|
||||||
import useRedirection from "@/hooks/useRedirection";
|
import useRedirection from "@/hooks/useRedirection";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
import getInitialData from "@/lib/client/getInitialData";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
@ -14,11 +15,11 @@ interface Props {
|
||||||
export default function Layout({ children }: Props) {
|
export default function Layout({ children }: Props) {
|
||||||
const { status } = useSession();
|
const { status } = useSession();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const redirection = useRedirection();
|
const redirection = useRedirection();
|
||||||
|
|
||||||
const routeExists = router.route === "/_error" ? false : true;
|
const routeExists = router.route === "/_error" ? false : true;
|
||||||
|
|
||||||
|
getInitialData();
|
||||||
|
|
||||||
if (status === "authenticated" && !redirection && routeExists)
|
if (status === "authenticated" && !redirection && routeExists)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
|
@ -0,0 +1,19 @@
|
||||||
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
import { prisma } from "@/lib/api/db";
|
||||||
|
import { Session } from "next-auth";
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse,
|
||||||
|
session: Session
|
||||||
|
) {
|
||||||
|
const collections = await prisma.collection.findMany({
|
||||||
|
where: {
|
||||||
|
ownerId: session?.user.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
response: collections || [],
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,18 +1,12 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { getServerSession } from "next-auth/next";
|
import { prisma } from "@/lib/api/db";
|
||||||
import { authOptions } from "pages/api/auth/[...nextauth]";
|
import { Session } from "next-auth";
|
||||||
import { prisma } from "@/lib/db";
|
|
||||||
|
|
||||||
type Data = {
|
|
||||||
response: object[] | string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function handler(
|
export default async function handler(
|
||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse<Data>
|
res: NextApiResponse,
|
||||||
|
session: Session
|
||||||
) {
|
) {
|
||||||
const session = await getServerSession(req, res, authOptions);
|
|
||||||
|
|
||||||
if (!session?.user?.email) {
|
if (!session?.user?.email) {
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
}
|
}
|
||||||
|
@ -39,44 +33,24 @@ export default async function handler(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(typeof session.user.id);
|
|
||||||
|
|
||||||
const checkIfCollectionExists = findCollection?.collections[0];
|
const checkIfCollectionExists = findCollection?.collections[0];
|
||||||
|
|
||||||
if (checkIfCollectionExists) {
|
if (checkIfCollectionExists) {
|
||||||
return res.status(400).json({ response: "Collection already exists." });
|
return res.status(400).json({ response: "Collection already exists." });
|
||||||
}
|
}
|
||||||
|
|
||||||
// const a = await prisma.user.update({
|
const createCollection = await prisma.collection.create({
|
||||||
// where: {
|
data: {
|
||||||
// id: session.user.id,
|
owner: {
|
||||||
// },
|
connect: {
|
||||||
// data: {
|
|
||||||
// // collections: {
|
|
||||||
// // create: { name: "Das" },
|
|
||||||
// // },
|
|
||||||
// },
|
|
||||||
// include: {
|
|
||||||
// collections: { include: { collection: true } },
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
await prisma.user.update({
|
|
||||||
where: {
|
|
||||||
id: session.user.id,
|
id: session.user.id,
|
||||||
},
|
},
|
||||||
data: {
|
},
|
||||||
collections: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
name: collectionName,
|
name: collectionName,
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
response: "Success",
|
response: createCollection,
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import useCollectionSlice from "@/store/collection";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
|
||||||
|
export default function getInitialData() {
|
||||||
|
const { status } = useSession();
|
||||||
|
const { setCollections } = useCollectionSlice();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (status === "authenticated") {
|
||||||
|
setCollections();
|
||||||
|
}
|
||||||
|
}, [status]);
|
||||||
|
}
|
|
@ -13,6 +13,10 @@
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.3.0",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^6.3.0",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.3.0",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@next/font": "13.1.6",
|
"@next/font": "13.1.6",
|
||||||
"@prisma/client": "^4.9.0",
|
"@prisma/client": "^4.9.0",
|
||||||
"@types/node": "18.11.18",
|
"@types/node": "18.11.18",
|
||||||
|
@ -25,7 +29,8 @@
|
||||||
"next-auth": "^4.19.1",
|
"next-auth": "^4.19.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"typescript": "4.9.4"
|
"typescript": "4.9.4",
|
||||||
|
"zustand": "^4.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcrypt": "^5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import MainLayout from "@/Layouts/MainLayout";
|
import React from "react";
|
||||||
|
import MainLayout from "@/layouts/MainLayout";
|
||||||
import "@/styles/globals.css";
|
import "@/styles/globals.css";
|
||||||
import { SessionProvider } from "next-auth/react";
|
import { SessionProvider } from "next-auth/react";
|
||||||
import type { AppProps } from "next/app";
|
import type { AppProps } from "next/app";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { prisma } from "@/lib/db";
|
import { prisma } from "@/lib/api/db";
|
||||||
import NextAuth from "next-auth/next";
|
import NextAuth from "next-auth/next";
|
||||||
import CredentialsProvider from "next-auth/providers/credentials";
|
import CredentialsProvider from "next-auth/providers/credentials";
|
||||||
import { AuthOptions } from "next-auth";
|
import { AuthOptions } from "next-auth";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { prisma } from "@/lib/db";
|
import { prisma } from "@/lib/api/db";
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcrypt";
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { getServerSession } from "next-auth/next";
|
import { getServerSession } from "next-auth/next";
|
||||||
import { authOptions } from "pages/api/auth/[...nextauth]";
|
import { authOptions } from "pages/api/auth/[...nextauth]";
|
||||||
import { prisma } from "@/lib/db";
|
import getCollections from "@/lib/api/controllers/collections/getCollections";
|
||||||
|
import postCollections from "@/lib/api/controllers/collections/postCollection";
|
||||||
|
|
||||||
type Data = {
|
type Data = {
|
||||||
response: object[] | string;
|
response: object[] | string;
|
||||||
|
@ -17,24 +18,7 @@ export default async function handler(
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
}
|
}
|
||||||
|
|
||||||
const email: string = session.user.email;
|
if (req.method === "GET") return await getCollections(req, res, session);
|
||||||
|
|
||||||
const findCollection = await prisma.user.findFirst({
|
if (req.method === "POST") return await postCollections(req, res, session);
|
||||||
where: {
|
|
||||||
email: email,
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
collections: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const collections = findCollection?.collections.map((e) => {
|
|
||||||
return { id: e.id, name: e.name, createdAt: e.createdAt };
|
|
||||||
});
|
|
||||||
|
|
||||||
// console.log(session?.user?.email);
|
|
||||||
|
|
||||||
return res.status(200).json({
|
|
||||||
response: collections || [],
|
|
||||||
});
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import Collections from "@/components/Collections";
|
import CollectionCards from "@/components/CollectionCards";
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
const { data: session, status } = useSession();
|
const { data: session, status } = useSession();
|
||||||
|
@ -7,9 +7,9 @@ export default function Dashboard() {
|
||||||
const user = session?.user;
|
const user = session?.user;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
// ml-80
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
<p className="text-3xl font-bold text-center mb-10">Linkwarden</p>
|
<CollectionCards />
|
||||||
<Collections />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { create } from "zustand";
|
||||||
|
import { Collection } from "@prisma/client";
|
||||||
|
|
||||||
|
type CollectionSlice = {
|
||||||
|
collections: Collection[];
|
||||||
|
setCollections: () => void;
|
||||||
|
addCollection: (collectionName: string) => void;
|
||||||
|
updateCollection: (collection: Collection) => void;
|
||||||
|
removeCollection: (collectionId: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useCollectionSlice = create<CollectionSlice>()((set) => ({
|
||||||
|
collections: [],
|
||||||
|
setCollections: async () => {
|
||||||
|
const response = await fetch("/api/routes/collections");
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (response.ok) set({ collections: data.response });
|
||||||
|
},
|
||||||
|
addCollection: async (collectionName) => {
|
||||||
|
const response = await fetch("/api/routes/collections", {
|
||||||
|
body: JSON.stringify({ collectionName }),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (response.ok)
|
||||||
|
set((state) => ({
|
||||||
|
collections: [...state.collections, data.response],
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
updateCollection: (collection) =>
|
||||||
|
set((state) => ({
|
||||||
|
collections: state.collections.map((c) =>
|
||||||
|
c.id === collection.id ? collection : c
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
removeCollection: (collectionId) => {
|
||||||
|
// await fetch("/api/routes/collections/postCollection", {
|
||||||
|
// body: JSON.stringify({ collectionName }),
|
||||||
|
// headers: {
|
||||||
|
// "Content-Type": "application/json",
|
||||||
|
// },
|
||||||
|
// method: "POST",
|
||||||
|
// })
|
||||||
|
// .then((res) => res.json())
|
||||||
|
// .then((data) => {
|
||||||
|
// console.log(data);
|
||||||
|
// set((state) => ({
|
||||||
|
// collections: [...state.collections, data.response],
|
||||||
|
// }));
|
||||||
|
// });
|
||||||
|
|
||||||
|
set((state) => ({
|
||||||
|
collections: state.collections.filter((c) => c.id !== collectionId),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default useCollectionSlice;
|
|
@ -1,3 +1,12 @@
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* Hide scrollbar */
|
||||||
|
.hidw-scrollbar::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.hide-scrollbar {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
45
yarn.lock
45
yarn.lock
|
@ -24,6 +24,39 @@
|
||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
|
"@fortawesome/fontawesome-common-types@6.3.0":
|
||||||
|
version "6.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.3.0.tgz#51f734e64511dbc3674cd347044d02f4dd26e86b"
|
||||||
|
integrity sha512-4BC1NMoacEBzSXRwKjZ/X/gmnbp/HU5Qqat7E8xqorUtBFZS+bwfGH5/wqOC2K6GV0rgEobp3OjGRMa5fK9pFg==
|
||||||
|
|
||||||
|
"@fortawesome/fontawesome-svg-core@^6.3.0":
|
||||||
|
version "6.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.3.0.tgz#b6a17d48d231ac1fad93e43fca7271676bf316cf"
|
||||||
|
integrity sha512-uz9YifyKlixV6AcKlOX8WNdtF7l6nakGyLYxYaCa823bEBqyj/U2ssqtctO38itNEwXb8/lMzjdoJ+aaJuOdrw==
|
||||||
|
dependencies:
|
||||||
|
"@fortawesome/fontawesome-common-types" "6.3.0"
|
||||||
|
|
||||||
|
"@fortawesome/free-regular-svg-icons@^6.3.0":
|
||||||
|
version "6.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.3.0.tgz#286f87f777e6c96af59151e86647c81083029ee2"
|
||||||
|
integrity sha512-cZnwiVHZ51SVzWHOaNCIA+u9wevZjCuAGSvSYpNlm6A4H4Vhwh8481Bf/5rwheIC3fFKlgXxLKaw8Xeroz8Ntg==
|
||||||
|
dependencies:
|
||||||
|
"@fortawesome/fontawesome-common-types" "6.3.0"
|
||||||
|
|
||||||
|
"@fortawesome/free-solid-svg-icons@^6.3.0":
|
||||||
|
version "6.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.3.0.tgz#d3bd33ae18bb15fdfc3ca136e2fea05f32768a65"
|
||||||
|
integrity sha512-x5tMwzF2lTH8pyv8yeZRodItP2IVlzzmBuD1M7BjawWgg9XAvktqJJ91Qjgoaf8qJpHQ8FEU9VxRfOkLhh86QA==
|
||||||
|
dependencies:
|
||||||
|
"@fortawesome/fontawesome-common-types" "6.3.0"
|
||||||
|
|
||||||
|
"@fortawesome/react-fontawesome@^0.2.0":
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4"
|
||||||
|
integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==
|
||||||
|
dependencies:
|
||||||
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.11.8":
|
"@humanwhocodes/config-array@^0.11.8":
|
||||||
version "0.11.8"
|
version "0.11.8"
|
||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
|
||||||
|
@ -2605,6 +2638,11 @@ uri-js@^4.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
|
use-sync-external-store@1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||||
|
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||||
|
|
||||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2:
|
util-deprecate@^1.0.1, util-deprecate@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
@ -2704,3 +2742,10 @@ yocto-queue@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||||
|
|
||||||
|
zustand@^4.3.3:
|
||||||
|
version "4.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.3.tgz#c9113499074dde2d6d99c1b5f591e9329572c224"
|
||||||
|
integrity sha512-x2jXq8S0kfLGNwGh87nhRfEc2eZy37tSatpSoSIN+O6HIaBhgQHSONV/F9VNrNcBcKQu/E80K1DeHDYQC/zCrQ==
|
||||||
|
dependencies:
|
||||||
|
use-sync-external-store "1.2.0"
|
||||||
|
|
Ŝarĝante…
Reference in New Issue