add pin to hover view + add number of pins to dashboard + bug fixes

This commit is contained in:
daniel31x13
2024-09-11 01:38:38 -04:00
parent fb1869ca7a
commit 9b1506a64e
11 changed files with 198 additions and 123 deletions
@@ -7,12 +7,12 @@ import usePermissions from "@/hooks/usePermissions";
import DeleteLinkModal from "@/components/ModalContent/DeleteLinkModal";
import { dropdownTriggerer } from "@/lib/client/utils";
import { useTranslation } from "next-i18next";
import { useUser } from "@/hooks/store/user";
import { useDeleteLink, useGetLink, useUpdateLink } from "@/hooks/store/links";
import { useDeleteLink, useGetLink } from "@/hooks/store/links";
import toast from "react-hot-toast";
import LinkModal from "@/components/ModalContent/LinkModal";
import { useRouter } from "next/router";
import clsx from "clsx";
import usePinLink from "@/lib/client/pinLink";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@@ -27,41 +27,14 @@ export default function LinkActions({ link, className, btnStyle }: Props) {
const permissions = usePermissions(link.collection.id as number);
const getLink = useGetLink();
const pinLink = usePinLink();
const [editLinkModal, setEditLinkModal] = useState(false);
const [linkModal, setLinkModal] = useState(false);
const [deleteLinkModal, setDeleteLinkModal] = useState(false);
const { data: user = {} } = useUser();
const updateLink = useUpdateLink();
const deleteLink = useDeleteLink();
const pinLink = async () => {
const isAlreadyPinned = link?.pinnedBy && link.pinnedBy[0] ? true : false;
const load = toast.loading(t("updating"));
await updateLink.mutateAsync(
{
...link,
pinnedBy: isAlreadyPinned ? [{ id: undefined }] : [{ id: user.id }],
},
{
onSettled: (data, error) => {
toast.dismiss(load);
if (error) {
toast.error(error.message);
} else {
toast.success(
isAlreadyPinned ? t("link_unpinned") : t("link_pinned")
);
}
},
}
);
};
const updateArchive = async () => {
const load = toast.loading(t("sending_request"));
@@ -103,7 +76,7 @@ export default function LinkActions({ link, className, btnStyle }: Props) {
</div>
) : (
<div
className={`dropdown dropdown-left absolute ${
className={`dropdown dropdown-end absolute ${
className || "top-3 right-3"
} z-20`}
>
@@ -117,7 +90,7 @@ export default function LinkActions({ link, className, btnStyle }: Props) {
</div>
<ul
className={
"dropdown-content z-[20] menu shadow bg-base-200 border border-neutral-content rounded-box mr-1"
"dropdown-content z-[20] menu shadow bg-base-200 border border-neutral-content rounded-box mt-1"
}
>
<li>
@@ -126,7 +99,7 @@ export default function LinkActions({ link, className, btnStyle }: Props) {
tabIndex={0}
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
pinLink();
pinLink(link);
}}
className="whitespace-nowrap"
>
@@ -216,7 +189,7 @@ export default function LinkActions({ link, className, btnStyle }: Props) {
{editLinkModal && (
<LinkModal
onClose={() => setEditLinkModal(false)}
onPin={pinLink}
onPin={() => pinLink(link)}
onUpdateArchive={updateArchive}
onDelete={() => setDeleteLinkModal(true)}
link={link}
@@ -232,7 +205,7 @@ export default function LinkActions({ link, className, btnStyle }: Props) {
{linkModal && (
<LinkModal
onClose={() => setLinkModal(false)}
onPin={pinLink}
onPin={() => pinLink(link)}
onUpdateArchive={updateArchive}
onDelete={() => setDeleteLinkModal(true)}
link={link}
@@ -23,6 +23,7 @@ import { useUser } from "@/hooks/store/user";
import { useGetLink, useLinks } from "@/hooks/store/links";
import { useRouter } from "next/router";
import useLocalSettingsStore from "@/store/localSettings";
import LinkPin from "./LinkPin";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
@@ -36,13 +37,13 @@ export default function LinkCard({ link, columns, editMode }: Props) {
const { t } = useTranslation();
const heightMap = {
1: "h-48",
2: "h-44",
3: "h-40",
4: "h-36",
5: "h-32",
6: "h-28",
7: "h-24",
1: "h-44",
2: "h-40",
3: "h-36",
4: "h-32",
5: "h-28",
6: "h-24",
7: "h-20",
8: "h-20",
};
@@ -216,7 +217,7 @@ export default function LinkCard({ link, columns, editMode }: Props) {
<div>
<hr className="divider mt-2 mb-1 last:hidden border-t border-neutral-content h-[1px]" />
<div className="flex justify-between text-xs text-neutral px-3 pb-1 gap-2">
<div className="flex justify-between items-center text-xs text-neutral px-3 pb-1 gap-2">
{show.collection && (
<div className="cursor-pointer truncate">
<LinkCollection link={link} collection={collection} />
@@ -238,6 +239,10 @@ export default function LinkCard({ link, columns, editMode }: Props) {
"top-3 right-3 group-hover:opacity-100 group-focus-within:opacity-100 opacity-0 duration-100"
}
/>
<LinkPin
link={link}
className="absolute top-3 right-[3.25rem] group-hover:opacity-100 group-focus-within:opacity-100 opacity-0 duration-100"
/>
</div>
);
}
@@ -35,13 +35,13 @@ export default function LinkMasonry({ link, editMode, columns }: Props) {
const { t } = useTranslation();
const heightMap = {
1: "h-48",
2: "h-44",
3: "h-40",
4: "h-36",
5: "h-32",
6: "h-28",
7: "h-24",
1: "h-44",
2: "h-40",
3: "h-36",
4: "h-32",
5: "h-28",
6: "h-24",
7: "h-20",
8: "h-20",
};
@@ -225,7 +225,7 @@ export default function LinkMasonry({ link, editMode, columns }: Props) {
<div>
<hr className="divider mt-2 mb-1 last:hidden border-t border-neutral-content h-[1px]" />
<div className="flex flex-wrap justify-between text-xs text-neutral px-3 pb-1 w-full gap-x-2">
<div className="flex flex-wrap justify-between items-center text-xs text-neutral px-3 pb-1 w-full gap-x-2">
{show.collection && (
<div className="cursor-pointer truncate">
<LinkCollection link={link} collection={collection} />
@@ -0,0 +1,35 @@
import { LinkIncludingShortenedCollectionAndTags } from "@/types/global";
import { useRouter } from "next/router";
import clsx from "clsx";
import usePinLink from "@/lib/client/pinLink";
type Props = {
link: LinkIncludingShortenedCollectionAndTags;
className?: string;
btnStyle?: string;
};
export default function LinkPin({ link, className, btnStyle }: Props) {
const pinLink = usePinLink();
const router = useRouter();
const isPublicRoute = router.pathname.startsWith("/public") ? true : false;
const isAlreadyPinned = link?.pinnedBy && link.pinnedBy[0] ? true : false;
return (
<div
className={clsx(className || "top-3 right-3 absolute", btnStyle)}
onClick={() => pinLink(link)}
>
<div className="btn btn-sm btn-square text-neutral">
<i
title="Pin"
className={clsx(
"text-xl",
isAlreadyPinned ? "bi-pin-fill" : "bi-pin"
)}
/>
</div>
</div>
);
}