added settings modal UI
This commit is contained in:
parent
a5d0d08c93
commit
e3862188de
|
@ -5,12 +5,15 @@ import { ChangeEventHandler } from "react";
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string;
|
label: string;
|
||||||
state: boolean;
|
state: boolean;
|
||||||
|
className?: string;
|
||||||
onClick: ChangeEventHandler<HTMLInputElement>;
|
onClick: ChangeEventHandler<HTMLInputElement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Checkbox({ label, state, onClick }: Props) {
|
export default function Checkbox({ label, state, className, onClick }: Props) {
|
||||||
return (
|
return (
|
||||||
<label className="cursor-pointer flex items-center gap-2 text-sky-500">
|
<label
|
||||||
|
className={`cursor-pointer flex items-center gap-2 text-sky-500 ${className}`}
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={state}
|
checked={state}
|
||||||
|
|
|
@ -46,7 +46,7 @@ export default function AddCollection({ toggleCollectionModal }: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3 sm:w-[35rem] w-80">
|
<div className="flex flex-col gap-3 sm:w-[35rem] w-80">
|
||||||
<p className="font-bold text-sky-300 mb-3 text-center">New Collection</p>
|
<p className="text-xl text-sky-500 mb-2 text-center">New Collection</p>
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row gap-3">
|
<div className="flex flex-col sm:flex-row gap-3">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
|
|
|
@ -78,7 +78,7 @@ export default function AddLink({ toggleLinkModal }: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3 sm:w-[35rem] w-80">
|
<div className="flex flex-col gap-3 sm:w-[35rem] w-80">
|
||||||
<p className="font-bold text-sky-300 mb-2 text-center">New Link</p>
|
<p className="text-xl text-sky-500 mb-2 text-center">New Link</p>
|
||||||
|
|
||||||
<div className="grid sm:grid-cols-2 gap-3">
|
<div className="grid sm:grid-cols-2 gap-3">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -11,12 +11,12 @@ import useCollectionStore from "@/store/collections";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
toggleCollectionModal: Function;
|
toggleDeleteCollectionModal: Function;
|
||||||
collection: ExtendedCollection;
|
collection: ExtendedCollection;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function AddCollection({
|
export default function AddCollection({
|
||||||
toggleCollectionModal,
|
toggleDeleteCollectionModal,
|
||||||
collection,
|
collection,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [inputField, setInputField] = useState("");
|
const [inputField, setInputField] = useState("");
|
||||||
|
@ -28,14 +28,14 @@ export default function AddCollection({
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
const response = await removeCollection(collection.id);
|
const response = await removeCollection(collection.id);
|
||||||
if (response) {
|
if (response) {
|
||||||
toggleCollectionModal();
|
toggleDeleteCollectionModal();
|
||||||
router.push("/collections");
|
router.push("/collections");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3 sm:w-[33rem] w-72">
|
<div className="flex flex-col gap-3 sm:w-[33rem] w-72">
|
||||||
<p className="font-bold text-sky-300 text-center">Delete Collection</p>
|
<p className="text-xl text-sky-500 mb-2 text-center">Delete Collection</p>
|
||||||
|
|
||||||
<p className="text-sky-900 select-none text-center">
|
<p className="text-sky-900 select-none text-center">
|
||||||
To confirm, type "
|
To confirm, type "
|
||||||
|
|
|
@ -54,7 +54,7 @@ export default function EditCollection({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3 sm:w-[35rem] w-80">
|
<div className="flex flex-col gap-3 sm:w-[35rem] w-80">
|
||||||
<p className="font-bold text-sky-300 mb-2 text-center">Edit Collection</p>
|
<p className="text-xl text-sky-500 mb-2 text-center">Edit Collection</p>
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row gap-3">
|
<div className="flex flex-col sm:flex-row gap-3">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
|
@ -297,7 +297,7 @@ export default function EditCollection({
|
||||||
<Modal toggleModal={toggleDeleteCollectionModal}>
|
<Modal toggleModal={toggleDeleteCollectionModal}>
|
||||||
<DeleteCollection
|
<DeleteCollection
|
||||||
collection={activeCollection}
|
collection={activeCollection}
|
||||||
toggleCollectionModal={toggleDeleteCollectionModal}
|
toggleDeleteCollectionModal={toggleDeleteCollectionModal}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default function EditLink({ toggleLinkModal, link }: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3 sm:w-96 w-80">
|
<div className="flex flex-col gap-3 sm:w-96 w-80">
|
||||||
<p className="font-bold text-sky-300 mb-2 text-center">Edit Link</p>
|
<p className="text-xl text-sky-500 mb-2 text-center">Edit Link</p>
|
||||||
<p className="text-sky-700">
|
<p className="text-sky-700">
|
||||||
<b>{shortendURL}</b> | {link.title}
|
<b>{shortendURL}</b> | {link.title}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -56,6 +56,7 @@ export default function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
// lg:ml-64 xl:ml-80
|
||||||
<div className="flex justify-between gap-2 items-center px-5 py-2 border-solid border-b-sky-100 border-b">
|
<div className="flex justify-between gap-2 items-center px-5 py-2 border-solid border-b-sky-100 border-b">
|
||||||
<div
|
<div
|
||||||
onClick={toggleSidebar}
|
onClick={toggleSidebar}
|
||||||
|
|
|
@ -5,21 +5,28 @@
|
||||||
|
|
||||||
import { prisma } from "@/lib/api/db";
|
import { prisma } from "@/lib/api/db";
|
||||||
|
|
||||||
export default async function (email: string) {
|
export default async function (lookupEmail: string, isSelf: boolean) {
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
where: {
|
where: {
|
||||||
email,
|
email: lookupEmail,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const unsensitiveUserInfo = {
|
const data = isSelf
|
||||||
|
? {
|
||||||
|
// If user is requesting its data
|
||||||
|
id: user?.id,
|
||||||
|
name: user?.name,
|
||||||
|
email: user?.email,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
// If user is requesting someone elses data
|
||||||
id: user?.id,
|
id: user?.id,
|
||||||
name: user?.name,
|
name: user?.name,
|
||||||
email: user?.email,
|
email: user?.email,
|
||||||
createdAt: user?.createdAt,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const statusCode = user?.id ? 200 : 404;
|
const statusCode = user?.id ? 200 : 404;
|
||||||
|
|
||||||
return { response: unsensitiveUserInfo || null, status: statusCode };
|
return { response: data || null, status: statusCode };
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,21 @@ import { useEffect } from "react";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import useTagStore from "@/store/tags";
|
import useTagStore from "@/store/tags";
|
||||||
import useLinkStore from "@/store/links";
|
import useLinkStore from "@/store/links";
|
||||||
|
import useAccountStore from "@/store/account";
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
const { status } = useSession();
|
const { status, data } = useSession();
|
||||||
const { setCollections } = useCollectionStore();
|
const { setCollections } = useCollectionStore();
|
||||||
const { setTags } = useTagStore();
|
const { setTags } = useTagStore();
|
||||||
const { setLinks } = useLinkStore();
|
const { setLinks } = useLinkStore();
|
||||||
|
const { setAccount } = useAccountStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status === "authenticated") {
|
if (status === "authenticated") {
|
||||||
setCollections();
|
setCollections();
|
||||||
setTags();
|
setTags();
|
||||||
setLinks();
|
setLinks();
|
||||||
|
setAccount(data.user.email as string);
|
||||||
}
|
}
|
||||||
}, [status]);
|
}, [status]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,12 @@ export default async function (req: NextApiRequest, res: NextApiResponse) {
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lookupEmail = req.query.email as string;
|
||||||
|
const isSelf = session.user.email === lookupEmail ? true : false;
|
||||||
|
|
||||||
// get unsensitive user info by email
|
// get unsensitive user info by email
|
||||||
if (req.method === "GET") {
|
if (req.method === "GET") {
|
||||||
const users = await getUsers(req.query.email as string);
|
const users = await getUsers(lookupEmail, isSelf);
|
||||||
return res.status(users.status).json({ response: users.response });
|
return res.status(users.status).json({ response: users.response });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,7 +175,7 @@ export default function () {
|
||||||
<Modal toggleModal={toggleDeleteCollectionModal}>
|
<Modal toggleModal={toggleDeleteCollectionModal}>
|
||||||
<DeleteCollection
|
<DeleteCollection
|
||||||
collection={activeCollection}
|
collection={activeCollection}
|
||||||
toggleCollectionModal={toggleDeleteCollectionModal}
|
toggleDeleteCollectionModal={toggleDeleteCollectionModal}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "User" ADD COLUMN "collectionProtection" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
ADD COLUMN "profilePhotoPath" TEXT NOT NULL DEFAULT '',
|
||||||
|
ADD COLUMN "whitelistedUsers" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
|
@ -20,6 +20,9 @@ model User {
|
||||||
collections Collection[]
|
collections Collection[]
|
||||||
tags Tag[]
|
tags Tag[]
|
||||||
collectionsJoined UsersAndCollections[]
|
collectionsJoined UsersAndCollections[]
|
||||||
|
collectionProtection Boolean @default(true)
|
||||||
|
whitelistedUsers String[] @default([])
|
||||||
|
profilePhotoPath String @default("")
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (C) 2022-present Daniel31x13 <daniel31x13@gmail.com>
|
||||||
|
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
// You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { create } from "zustand";
|
||||||
|
import { User } from "@prisma/client";
|
||||||
|
|
||||||
|
type AccountStore = {
|
||||||
|
account: User;
|
||||||
|
setAccount: (email: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useAccountStore = create<AccountStore>()((set) => ({
|
||||||
|
account: {} as User,
|
||||||
|
setAccount: async (email) => {
|
||||||
|
const response = await fetch(`/api/routes/users?email=${email}`);
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
if (response.ok) set({ account: data.response });
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default useAccountStore;
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { Tag } from "@prisma/client";
|
import { Tag } from "@prisma/client";
|
||||||
import tags from "@/pages/api/routes/tags";
|
|
||||||
|
|
||||||
type TagStore = {
|
type TagStore = {
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
|
Ŝarĝante…
Reference in New Issue