many breaking changes/fixes
This commit is contained in:
@@ -15,7 +15,10 @@ export default function ({ collection }: { collection: Collection }) {
|
||||
<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">
|
||||
<p className="text-lg w-max">{collection.name}</p>
|
||||
<FontAwesomeIcon icon={faChevronRight} className="w-3" />
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronRight}
|
||||
className="w-3 h-3 text-gray-500"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-sky-300 font-bold">{formattedDate}</p>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,17 @@ import CreatableSelect from "react-select/creatable";
|
||||
import { styles } from "./styles";
|
||||
import { Options } from "./types";
|
||||
|
||||
export default function ({ onChange }: any) {
|
||||
type Props = {
|
||||
onChange: any;
|
||||
defaultValue:
|
||||
| {
|
||||
value: number;
|
||||
label: string;
|
||||
}
|
||||
| undefined;
|
||||
};
|
||||
|
||||
export default function ({ onChange, defaultValue }: Props) {
|
||||
const { collections } = useCollectionStore();
|
||||
const router = useRouter();
|
||||
|
||||
@@ -17,10 +27,8 @@ export default function ({ onChange }: any) {
|
||||
return e.id === collectionId;
|
||||
});
|
||||
|
||||
let defaultCollection = null;
|
||||
|
||||
if (activeCollection) {
|
||||
defaultCollection = {
|
||||
if (activeCollection && !defaultValue) {
|
||||
defaultValue = {
|
||||
value: activeCollection?.id,
|
||||
label: activeCollection?.name,
|
||||
};
|
||||
@@ -28,7 +36,7 @@ export default function ({ onChange }: any) {
|
||||
|
||||
useEffect(() => {
|
||||
const formatedCollections = collections.map((e) => {
|
||||
return { value: e.id, label: e.name };
|
||||
return { value: e.id, label: e.name, ownerId: e.ownerId };
|
||||
});
|
||||
|
||||
setOptions(formatedCollections);
|
||||
@@ -40,7 +48,7 @@ export default function ({ onChange }: any) {
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
styles={styles}
|
||||
defaultValue={defaultCollection}
|
||||
defaultValue={defaultValue}
|
||||
menuPosition="fixed"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,15 @@ import CreatableSelect from "react-select/creatable";
|
||||
import { styles } from "./styles";
|
||||
import { Options } from "./types";
|
||||
|
||||
export default function ({ onChange }: any) {
|
||||
type Props = {
|
||||
onChange: any;
|
||||
defaultValue?: {
|
||||
value: number;
|
||||
label: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export default function ({ onChange, defaultValue }: Props) {
|
||||
const { tags } = useTagStore();
|
||||
|
||||
const [options, setOptions] = useState<Options[]>([]);
|
||||
@@ -23,6 +31,7 @@ export default function ({ onChange }: any) {
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
styles={styles}
|
||||
defaultValue={defaultValue}
|
||||
menuPosition="fixed"
|
||||
isMulti
|
||||
/>
|
||||
|
||||
+36
-20
@@ -3,17 +3,17 @@ import {
|
||||
faFolder,
|
||||
faArrowUpRightFromSquare,
|
||||
faEllipsis,
|
||||
faStar,
|
||||
faPenToSquare,
|
||||
faTrashCan,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faFileImage, faFilePdf } from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import Dropdown from "./Dropdown";
|
||||
import useLinkStore from "@/store/links";
|
||||
import Modal from "./Modal";
|
||||
import EditLink from "./Modal/EditLink";
|
||||
|
||||
export default function ({
|
||||
link,
|
||||
@@ -23,6 +23,7 @@ export default function ({
|
||||
count: number;
|
||||
}) {
|
||||
const [editDropdown, setEditDropdown] = useState(false);
|
||||
const [editModal, setEditModal] = useState(false);
|
||||
const [archiveLabel, setArchiveLabel] = useState("Archived Formats");
|
||||
|
||||
const { removeLink } = useLinkStore();
|
||||
@@ -34,14 +35,24 @@ export default function ({
|
||||
day: "numeric",
|
||||
});
|
||||
|
||||
const toggleEditModal = () => {
|
||||
setEditModal(!editModal);
|
||||
};
|
||||
|
||||
return (
|
||||
<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">
|
||||
<div className="border border-sky-100 bg-gray-100 p-5 rounded-md flex items-start relative gap-5 sm:gap-14 group/item">
|
||||
{editModal ? (
|
||||
<Modal toggleModal={toggleEditModal}>
|
||||
<EditLink toggleLinkModal={toggleEditModal} link={link} />
|
||||
</Modal>
|
||||
) : null}
|
||||
|
||||
<Image
|
||||
src={`http://icons.duckduckgo.com/ip3/${shortendURL}.ico`}
|
||||
width={32}
|
||||
height={32}
|
||||
alt=""
|
||||
className="opacity-100 duration-100 select-none mt-3"
|
||||
className="select-none mt-3 z-10 rounded-md"
|
||||
draggable="false"
|
||||
onError={(e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
@@ -53,7 +64,7 @@ export default function ({
|
||||
width={80}
|
||||
height={80}
|
||||
alt=""
|
||||
className="blur-sm absolute left-0 opacity-50 select-none"
|
||||
className="blur-sm absolute left-2 opacity-50 select-none hidden sm:block"
|
||||
draggable="false"
|
||||
onError={(e) => {
|
||||
const target = e.target as HTMLElement;
|
||||
@@ -65,9 +76,6 @@ export default function ({
|
||||
<div className="flex items-baseline gap-1">
|
||||
<p className="text-sm text-sky-300 font-bold">{count + 1}.</p>
|
||||
<p className="text-lg text-sky-600">{link.name}</p>
|
||||
{link.starred ? (
|
||||
<FontAwesomeIcon icon={faStar} className="w-3 text-amber-400" />
|
||||
) : null}
|
||||
</div>
|
||||
<p className="text-sky-400 text-sm font-medium">{link.title}</p>
|
||||
<div className="flex gap-3 items-center flex-wrap my-3">
|
||||
@@ -101,20 +109,25 @@ export default function ({
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col justify-between items-end relative">
|
||||
<FontAwesomeIcon
|
||||
icon={faEllipsis}
|
||||
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"
|
||||
<div
|
||||
onClick={() => setEditDropdown(!editDropdown)}
|
||||
id="edit-dropdown"
|
||||
/>
|
||||
className="text-gray-500 inline-flex rounded-md cursor-pointer hover:bg-white hover:outline outline-sky-100 outline-1 duration-100 p-1"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faEllipsis}
|
||||
title="More"
|
||||
className="w-6 h-6"
|
||||
id="edit-dropdown"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-center text-sky-400 text-sm font-bold">
|
||||
{archiveLabel}
|
||||
</p>
|
||||
|
||||
<div
|
||||
className="flex justify-between mt-3 gap-3"
|
||||
className="flex justify-center mt-3 gap-3"
|
||||
onMouseLeave={() => setArchiveLabel("Archived Formats")}
|
||||
>
|
||||
<a
|
||||
@@ -152,25 +165,28 @@ export default function ({
|
||||
{editDropdown ? (
|
||||
<Dropdown
|
||||
items={[
|
||||
{
|
||||
name: "Star",
|
||||
icon: <FontAwesomeIcon icon={faStar} />,
|
||||
},
|
||||
{
|
||||
name: "Edit",
|
||||
icon: <FontAwesomeIcon icon={faPenToSquare} />,
|
||||
onClick: () => {
|
||||
setEditModal(true);
|
||||
setEditDropdown(false);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Delete",
|
||||
icon: <FontAwesomeIcon icon={faTrashCan} />,
|
||||
onClick: () => removeLink(link),
|
||||
onClick: () => {
|
||||
removeLink(link);
|
||||
setEditDropdown(false);
|
||||
},
|
||||
},
|
||||
]}
|
||||
onClickOutside={(e: Event) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target.id !== "edit-dropdown") setEditDropdown(false);
|
||||
}}
|
||||
className="absolute top-8 right-0"
|
||||
className="absolute top-9 right-0"
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -1,46 +1,76 @@
|
||||
import React, { useState } from "react";
|
||||
import CollectionSelection from "./InputSelect/CollectionSelection";
|
||||
import TagSelection from "./InputSelect/TagSelection";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import CollectionSelection from "@/components/InputSelect/CollectionSelection";
|
||||
import TagSelection from "@/components/InputSelect/TagSelection";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { useRouter } from "next/router";
|
||||
import { NewLink } from "@/types/global";
|
||||
import { ExtendedLink, NewLink } from "@/types/global";
|
||||
import useLinkStore from "@/store/links";
|
||||
import { useRouter } from "next/router";
|
||||
import useCollectionStore from "@/store/collections";
|
||||
|
||||
export default function ({ toggleLinkModal }: { toggleLinkModal: Function }) {
|
||||
type Props = {
|
||||
toggleLinkModal: Function;
|
||||
};
|
||||
|
||||
export default function AddLink({ toggleLinkModal }: Props) {
|
||||
const router = useRouter();
|
||||
|
||||
const [newLink, setNewLink] = useState<NewLink>({
|
||||
name: "",
|
||||
url: "",
|
||||
tags: [],
|
||||
collection: { id: Number(router.query.id) },
|
||||
collection: {
|
||||
id: undefined,
|
||||
name: "",
|
||||
ownerId: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const { addLink } = useLinkStore();
|
||||
const { collections } = useCollectionStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (router.query.id) {
|
||||
const currentCollection = collections.find(
|
||||
(e) => e.id == Number(router.query.id)
|
||||
);
|
||||
|
||||
setNewLink({
|
||||
...newLink,
|
||||
collection: {
|
||||
id: currentCollection?.id,
|
||||
name: currentCollection?.name,
|
||||
ownerId: currentCollection?.ownerId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
const setTags = (e: any) => {
|
||||
const tagNames = e.map((e: any) => {
|
||||
return e.label;
|
||||
return { name: e.label };
|
||||
});
|
||||
|
||||
setNewLink({ ...newLink, tags: tagNames });
|
||||
};
|
||||
|
||||
const setCollection = (e: any) => {
|
||||
const collection = { id: e?.value, isNew: e?.__isNew__ };
|
||||
if (e?.__isNew__) e.value = null;
|
||||
|
||||
setNewLink({ ...newLink, collection: collection });
|
||||
setNewLink({
|
||||
...newLink,
|
||||
collection: { id: e?.value, name: e?.label, ownerId: e?.ownerId },
|
||||
});
|
||||
};
|
||||
|
||||
const submitLink = async () => {
|
||||
const response = await addLink(newLink);
|
||||
console.log(newLink);
|
||||
|
||||
const response = await addLink(newLink as ExtendedLink);
|
||||
|
||||
if (response) toggleLinkModal();
|
||||
};
|
||||
|
||||
return (
|
||||
<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">
|
||||
<div className="flex flex-col gap-3">
|
||||
<p className="font-bold text-sky-300 mb-2 text-center">New Link</p>
|
||||
|
||||
<div className="flex gap-5 items-center justify-between">
|
||||
@@ -72,7 +102,14 @@ export default function ({ toggleLinkModal }: { toggleLinkModal: Function }) {
|
||||
|
||||
<div className="flex gap-5 items-center justify-between">
|
||||
<p className="text-sm font-bold text-sky-300">Collection</p>
|
||||
<CollectionSelection onChange={setCollection} />
|
||||
<CollectionSelection
|
||||
defaultValue={
|
||||
newLink.collection.name && newLink.collection.id
|
||||
? { value: newLink.collection.id, label: newLink.collection.name }
|
||||
: undefined
|
||||
}
|
||||
onChange={setCollection}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -0,0 +1,101 @@
|
||||
import React, { useState } from "react";
|
||||
import CollectionSelection from "@/components/InputSelect/CollectionSelection";
|
||||
import TagSelection from "@/components/InputSelect/TagSelection";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { ExtendedLink } from "@/types/global";
|
||||
import { faPenToSquare } from "@fortawesome/free-regular-svg-icons";
|
||||
import useLinkStore from "@/store/links";
|
||||
|
||||
type Props = {
|
||||
toggleLinkModal: Function;
|
||||
link: ExtendedLink;
|
||||
};
|
||||
|
||||
export default function EditLink({ toggleLinkModal, link }: Props) {
|
||||
const [currentLink, setCurrentLink] = useState<ExtendedLink>(link);
|
||||
|
||||
const { updateLink } = useLinkStore();
|
||||
|
||||
const setTags = (e: any) => {
|
||||
const tagNames = e.map((e: any) => {
|
||||
return { name: e.label };
|
||||
});
|
||||
|
||||
setCurrentLink({ ...currentLink, tags: tagNames });
|
||||
};
|
||||
|
||||
const setCollection = (e: any) => {
|
||||
if (e?.__isNew__) e.value = null;
|
||||
|
||||
setCurrentLink({
|
||||
...currentLink,
|
||||
collection: { id: e?.value, name: e?.label, ownerId: e?.ownerId } as any,
|
||||
});
|
||||
};
|
||||
|
||||
const submitLink = async () => {
|
||||
updateLink(currentLink);
|
||||
toggleLinkModal();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<p className="font-bold text-sky-300 mb-2 text-center">New Link</p>
|
||||
|
||||
<div className="flex gap-5 items-center justify-between">
|
||||
<p className="text-sm font-bold text-sky-300">Name</p>
|
||||
<input
|
||||
value={currentLink.name}
|
||||
onChange={(e) =>
|
||||
setCurrentLink({ ...currentLink, name: e.target.value })
|
||||
}
|
||||
type="text"
|
||||
placeholder="e.g. Example Link"
|
||||
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 className="flex gap-5 items-center justify-between">
|
||||
<p className="text-sm font-bold text-sky-300">URL</p>
|
||||
<input
|
||||
value={currentLink.url}
|
||||
onChange={(e) =>
|
||||
setCurrentLink({ ...currentLink, url: e.target.value })
|
||||
}
|
||||
type="text"
|
||||
placeholder="e.g. http://example.com/"
|
||||
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 className="flex gap-5 items-center justify-between">
|
||||
<p className="text-sm font-bold text-sky-300">Tags</p>
|
||||
<TagSelection
|
||||
onChange={setTags}
|
||||
defaultValue={link.tags.map((e) => {
|
||||
return { label: e.name, value: e.id };
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-5 items-center justify-between">
|
||||
<p className="text-sm font-bold text-sky-300">Collection</p>
|
||||
<CollectionSelection
|
||||
onChange={setCollection}
|
||||
defaultValue={{
|
||||
label: link.collection.name,
|
||||
value: link.collection.id,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
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}
|
||||
>
|
||||
<FontAwesomeIcon icon={faPenToSquare} className="h-5" />
|
||||
Edit Link
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { ReactNode } from "react";
|
||||
import ClickAwayHandler from "@/components/ClickAwayHandler";
|
||||
|
||||
type Props = {
|
||||
toggleModal: Function;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export default function ({ toggleModal, children }: Props) {
|
||||
return (
|
||||
<div className="fixed top-0 bottom-0 right-0 left-0 bg-gray-500 bg-opacity-10 flex items-center fade-in z-30">
|
||||
<ClickAwayHandler onClickOutside={toggleModal} className="w-fit mx-auto">
|
||||
<div className="slide-up border-sky-100 rounded-md border-solid border shadow-lg p-5 bg-white">
|
||||
{children}
|
||||
</div>
|
||||
</ClickAwayHandler>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+76
-88
@@ -1,62 +1,25 @@
|
||||
import { useRouter } from "next/router";
|
||||
import useCollectionStore from "@/store/collections";
|
||||
import { Collection, Tag } from "@prisma/client";
|
||||
import ClickAwayHandler from "./ClickAwayHandler";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { signOut } from "next-auth/react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import {
|
||||
faPlus,
|
||||
faFolder,
|
||||
faBox,
|
||||
faHashtag,
|
||||
faBookmark,
|
||||
faMagnifyingGlass,
|
||||
IconDefinition,
|
||||
faCircleUser,
|
||||
faSliders,
|
||||
faArrowRightFromBracket,
|
||||
faChevronDown,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { useEffect, useState } from "react";
|
||||
import AddLinkModal from "./AddLinkModal";
|
||||
import useTagStore from "@/store/tags";
|
||||
import { useState } from "react";
|
||||
import Dropdown from "@/components/Dropdown";
|
||||
import Modal from "./Modal";
|
||||
import AddLink from "./Modal/AddLink";
|
||||
|
||||
export default function () {
|
||||
const router = useRouter();
|
||||
const [pageName, setPageName] = useState<string | null>("");
|
||||
const [pageIcon, setPageIcon] = useState<IconDefinition | null>(null);
|
||||
const { data: session } = useSession();
|
||||
|
||||
const { collections } = useCollectionStore();
|
||||
const { tags } = useTagStore();
|
||||
const [profileDropdown, setProfileDropdown] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (router.route === "/collections/[id]") {
|
||||
const collectionId = router.query.id;
|
||||
|
||||
const activeCollection: Collection | undefined = collections.find(
|
||||
(e) => e.id.toString() == collectionId
|
||||
);
|
||||
|
||||
if (activeCollection) {
|
||||
setPageName(activeCollection?.name);
|
||||
}
|
||||
|
||||
setPageIcon(faFolder);
|
||||
} else if (router.route === "/tags/[id]") {
|
||||
const tagId = router.query.id;
|
||||
|
||||
const activeTag: Tag | undefined = tags.find(
|
||||
(e) => e.id.toString() == tagId
|
||||
);
|
||||
|
||||
if (activeTag) {
|
||||
setPageName(activeTag?.name);
|
||||
}
|
||||
|
||||
setPageIcon(faHashtag);
|
||||
} else if (router.route === "/collections") {
|
||||
setPageName("All Collections");
|
||||
setPageIcon(faBox);
|
||||
} else if (router.route === "/links") {
|
||||
setPageName("All Links");
|
||||
setPageIcon(faBookmark);
|
||||
}
|
||||
}, [router, collections, tags]);
|
||||
const user = session?.user;
|
||||
|
||||
const [linkModal, setLinkModal] = useState(false);
|
||||
|
||||
@@ -65,50 +28,75 @@ export default function () {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-between items-center p-2 border-solid border-b-sky-100 border-b">
|
||||
<div className="text-sky-900 rounded-md my-1 flex items-center gap-2 font-bold">
|
||||
{pageIcon ? (
|
||||
<FontAwesomeIcon icon={pageIcon} className="w-4 text-sky-300" />
|
||||
) : null}
|
||||
<p>{pageName}</p>
|
||||
<div className="flex justify-between gap-2 items-center px-5 py-2 border-solid border-b-sky-100 border-b">
|
||||
<div className="flex items-center relative">
|
||||
<label
|
||||
htmlFor="search-box"
|
||||
className="inline-flex w-fit absolute right-0 cursor-pointer select-none rounded-md p-1 text-sky-500"
|
||||
>
|
||||
<FontAwesomeIcon icon={faMagnifyingGlass} className="w-5 h-5" />
|
||||
</label>
|
||||
<input
|
||||
id="search-box"
|
||||
type="text"
|
||||
placeholder="Search for Links"
|
||||
className="border border-sky-100 rounded-md pr-6 w-60 focus:border-sky-500 sm:focus:w-80 hover:border-sky-500 duration-100 outline-none p-1 text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<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
|
||||
icon={faPlus}
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
onClick={toggleLinkModal}
|
||||
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"
|
||||
/>
|
||||
className="inline-flex gap-1 items-center select-none cursor-pointer p-1 text-sky-500 rounded-md hover:outline-sky-500 outline duration-100 bg-white outline-sky-100 outline-1"
|
||||
>
|
||||
<FontAwesomeIcon icon={faPlus} className="w-5 h-5" />
|
||||
</div>
|
||||
|
||||
{linkModal ? (
|
||||
<div className="fixed top-0 bottom-0 right-0 left-0 bg-gray-500 bg-opacity-10 flex items-center fade-in z-10">
|
||||
<ClickAwayHandler
|
||||
onClickOutside={toggleLinkModal}
|
||||
className="w-fit mx-auto"
|
||||
>
|
||||
<AddLinkModal toggleLinkModal={toggleLinkModal} />
|
||||
</ClickAwayHandler>
|
||||
</div>
|
||||
<Modal toggleModal={toggleLinkModal}>
|
||||
<AddLink toggleLinkModal={toggleLinkModal} />
|
||||
</Modal>
|
||||
) : null}
|
||||
|
||||
<div className="relative">
|
||||
<div
|
||||
className="flex gap-2 items-center p-1 w-fit bg-white text-gray-600 cursor-pointer border border-sky-100 hover:border-sky-500 rounded-md duration-100"
|
||||
onClick={() => setProfileDropdown(!profileDropdown)}
|
||||
id="profile-dropdown"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faCircleUser}
|
||||
className="h-5 w-5 pointer-events-none"
|
||||
/>
|
||||
<div className="flex items-center gap-1 pointer-events-none">
|
||||
<p className="font-bold leading-3">{user?.name}</p>
|
||||
<FontAwesomeIcon icon={faChevronDown} className="h-3 w-3" />
|
||||
</div>
|
||||
</div>
|
||||
{profileDropdown ? (
|
||||
<Dropdown
|
||||
items={[
|
||||
{
|
||||
name: "Settings",
|
||||
icon: <FontAwesomeIcon icon={faSliders} />,
|
||||
},
|
||||
{
|
||||
name: "Logout",
|
||||
icon: <FontAwesomeIcon icon={faArrowRightFromBracket} />,
|
||||
onClick: () => {
|
||||
signOut();
|
||||
setProfileDropdown(!profileDropdown);
|
||||
},
|
||||
},
|
||||
]}
|
||||
onClickOutside={(e: Event) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target.id !== "profile-dropdown") setProfileDropdown(false);
|
||||
}}
|
||||
className="absolute top-8 right-0 z-20"
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,37 +1,25 @@
|
||||
import { useSession } from "next-auth/react";
|
||||
import ClickAwayHandler from "@/components/ClickAwayHandler";
|
||||
import { useState } from "react";
|
||||
import useCollectionStore from "@/store/collections";
|
||||
import { signOut } from "next-auth/react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faPlus,
|
||||
faChevronDown,
|
||||
faFolder,
|
||||
faBox,
|
||||
faHashtag,
|
||||
faBookmark,
|
||||
faCircleUser,
|
||||
faSliders,
|
||||
faArrowRightFromBracket,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import SidebarItem from "./SidebarItem";
|
||||
import useTagStore from "@/store/tags";
|
||||
import Link from "next/link";
|
||||
import Dropdown from "@/components/Dropdown";
|
||||
|
||||
export default function () {
|
||||
const { data: session } = useSession();
|
||||
|
||||
const [collectionInput, setCollectionInput] = useState(false);
|
||||
const [profileDropdown, setProfileDropdown] = useState(false);
|
||||
|
||||
const { collections, addCollection } = useCollectionStore();
|
||||
|
||||
const { tags } = useTagStore();
|
||||
|
||||
const user = session?.user;
|
||||
|
||||
const toggleCollectionInput = () => {
|
||||
setCollectionInput(!collectionInput);
|
||||
};
|
||||
@@ -48,48 +36,12 @@ export default function () {
|
||||
};
|
||||
|
||||
return (
|
||||
<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="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)}
|
||||
id="profile-dropdown"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faCircleUser}
|
||||
className="h-5 pointer-events-none"
|
||||
/>
|
||||
<div className="flex items-center gap-1 pointer-events-none">
|
||||
<p className="font-bold">{user?.name}</p>
|
||||
<FontAwesomeIcon icon={faChevronDown} className="h-3" />
|
||||
</div>
|
||||
</div>
|
||||
{profileDropdown ? (
|
||||
<Dropdown
|
||||
items={[
|
||||
{
|
||||
name: "Settings",
|
||||
icon: <FontAwesomeIcon icon={faSliders} />,
|
||||
},
|
||||
{
|
||||
name: "Logout",
|
||||
icon: <FontAwesomeIcon icon={faArrowRightFromBracket} />,
|
||||
onClick: () => {
|
||||
signOut();
|
||||
setProfileDropdown(!profileDropdown);
|
||||
},
|
||||
},
|
||||
]}
|
||||
onClickOutside={(e: Event) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target.id !== "profile-dropdown") setProfileDropdown(false);
|
||||
}}
|
||||
className="absolute top-10 left-0"
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<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-20">
|
||||
<p className="p-2 text-sky-500 font-bold text-xl mb-5 leading-4">
|
||||
Linkwarden
|
||||
</p>
|
||||
|
||||
<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-md my-1 p-2 cursor-pointer flex items-center gap-2">
|
||||
<FontAwesomeIcon icon={faBookmark} className="w-4 text-sky-300" />
|
||||
<p>All Links</p>
|
||||
@@ -119,12 +71,13 @@ export default function () {
|
||||
/>
|
||||
</ClickAwayHandler>
|
||||
) : (
|
||||
<FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
onClick={toggleCollectionInput}
|
||||
<div
|
||||
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"
|
||||
/>
|
||||
onClick={toggleCollectionInput}
|
||||
className="select-none text-gray-500 rounded-md cursor-pointer hover:bg-white hover:outline outline-sky-100 outline-1 duration-100 p-1"
|
||||
>
|
||||
<FontAwesomeIcon icon={faPlus} className="h-3 w-3" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user