mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-10 07:25:35 +00:00
feat; add quick actions + change icons
This commit is contained in:
@@ -1,52 +1,31 @@
|
||||
import LinkTag from "next/link";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
AiFillDelete,
|
||||
AiFillEdit,
|
||||
AiFillStar,
|
||||
AiOutlineStar,
|
||||
} from "react-icons/ai";
|
||||
import { AiFillStar } from "react-icons/ai";
|
||||
|
||||
import { Link } from "types";
|
||||
|
||||
import EditItem from "components/QuickActions/EditItem";
|
||||
import FavoriteItem from "components/QuickActions/FavoriteItem";
|
||||
import RemoveItem from "components/QuickActions/RemoveItem";
|
||||
import LinkFavicon from "./LinkFavicon";
|
||||
|
||||
import styles from "./links.module.scss";
|
||||
|
||||
export default function LinkItem({ link }: { link: Link }) {
|
||||
const { id, name, url, favorite } = link;
|
||||
const [isFavorite, setFavorite] = useState(favorite);
|
||||
|
||||
return (
|
||||
<li className={styles["link"]} key={id}>
|
||||
<LinkFavicon url={url} />
|
||||
<LinkTag href={url} target={"_blank"} rel={"noreferrer"}>
|
||||
<span className={styles["link-name"]}>
|
||||
{name} {isFavorite && <AiFillStar color="#ffc107" />}
|
||||
{name} {favorite && <AiFillStar color="#ffc107" />}
|
||||
</span>
|
||||
<LinkItemURL url={url} />
|
||||
</LinkTag>
|
||||
<div className={styles["controls"]}>
|
||||
<div onClick={() => setFavorite((v) => !v)} className={styles["edit"]}>
|
||||
{isFavorite ? (
|
||||
<AiFillStar color="#ffc107" />
|
||||
) : (
|
||||
<AiOutlineStar color="#ffc107" />
|
||||
)}
|
||||
</div>
|
||||
<LinkTag
|
||||
href={`/link/edit/${id}`}
|
||||
className={styles["edit"]}
|
||||
title="Edit link"
|
||||
>
|
||||
<AiFillEdit />
|
||||
</LinkTag>
|
||||
<LinkTag
|
||||
href={`/link/remove/${id}`}
|
||||
className={styles["remove"]}
|
||||
title="Remove link"
|
||||
>
|
||||
<AiFillDelete color="red" />
|
||||
</LinkTag>
|
||||
<FavoriteItem isFavorite={favorite} />
|
||||
<EditItem type="link" id={id} />
|
||||
<RemoveItem type="link" id={id} />
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import LinkTag from "next/link";
|
||||
|
||||
import { Category } from "types";
|
||||
|
||||
import EditItem from "components/QuickActions/EditItem";
|
||||
import RemoveItem from "components/QuickActions/RemoveItem";
|
||||
import LinkItem from "./LinkItem";
|
||||
|
||||
import styles from "./links.module.scss";
|
||||
@@ -15,25 +18,29 @@ export default function Links({ category }: { category: Category }) {
|
||||
);
|
||||
}
|
||||
|
||||
const { name, links } = category;
|
||||
const { id, name, links } = category;
|
||||
if (links.length === 0) {
|
||||
return (
|
||||
<div className={styles["no-link"]}>
|
||||
<p>
|
||||
Aucun lien pour <b>{category.name}</b>
|
||||
Aucun lien pour <b>{name}</b>
|
||||
</p>
|
||||
<LinkTag href={`/link/create?categoryId=${category.id}`}>
|
||||
Créer un lien
|
||||
</LinkTag>
|
||||
<LinkTag href={`/link/create?categoryId=${id}`}>Créer un lien</LinkTag>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles["links-wrapper"]}>
|
||||
<h2>
|
||||
{name}
|
||||
<span className={styles["links-count"]}> — {links.length}</span>
|
||||
<h2 className={styles["category-header"]}>
|
||||
<span>
|
||||
{name}
|
||||
<span className={styles["links-count"]}> — {links.length}</span>
|
||||
</span>
|
||||
<span className={styles["category-controls"]}>
|
||||
<EditItem type="category" id={id} />
|
||||
<RemoveItem type="category" id={id} />
|
||||
</span>
|
||||
</h2>
|
||||
<ul className={styles["links"]} key={Math.random()}>
|
||||
{links.map((link, key) => (
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
& h2 {
|
||||
color: $blue;
|
||||
@@ -33,12 +31,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
.category-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
& .category-controls {
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.links {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 0.5em;
|
||||
padding: 3px;
|
||||
flex-direction: column;
|
||||
animation: fadein 0.3s both; // bug on drag start
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.link {
|
||||
@@ -48,10 +63,9 @@
|
||||
width: 100%;
|
||||
color: $blue;
|
||||
background-color: $white;
|
||||
padding: 10px 15px;
|
||||
padding: 0.75em 1em;
|
||||
border: 1px solid $lightest-grey;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 10px;
|
||||
outline: 3px solid transparent;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
27
src/components/QuickActions/CreateItem.tsx
Normal file
27
src/components/QuickActions/CreateItem.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import LinkTag from "next/link";
|
||||
import { GrAdd } from "react-icons/gr";
|
||||
|
||||
import { Category } from "types";
|
||||
|
||||
import styles from "./quickactions.module.scss";
|
||||
|
||||
export default function CreateItem({
|
||||
type,
|
||||
categoryId,
|
||||
onClick,
|
||||
}: {
|
||||
type: "category" | "link";
|
||||
categoryId: Category["id"];
|
||||
onClick?: (event: any) => void; // FIXME: find good event type
|
||||
}) {
|
||||
return (
|
||||
<LinkTag
|
||||
href={`/${type}/create${categoryId && `?categoryId=${categoryId}`}`}
|
||||
title={`Create ${type}`}
|
||||
className={styles["action"]}
|
||||
onClick={onClick && onClick}
|
||||
>
|
||||
<GrAdd />
|
||||
</LinkTag>
|
||||
);
|
||||
}
|
||||
27
src/components/QuickActions/EditItem.tsx
Normal file
27
src/components/QuickActions/EditItem.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import LinkTag from "next/link";
|
||||
import { AiOutlineEdit } from "react-icons/ai";
|
||||
|
||||
import { Category, Link } from "types";
|
||||
|
||||
import styles from "./quickactions.module.scss";
|
||||
|
||||
export default function EditItem({
|
||||
type,
|
||||
id,
|
||||
onClick,
|
||||
}: {
|
||||
type: "category" | "link";
|
||||
id: Link["id"] | Category["id"];
|
||||
onClick?: (event: any) => void; // FIXME: find good event type
|
||||
}) {
|
||||
return (
|
||||
<LinkTag
|
||||
href={`/${type}/edit/${id}`}
|
||||
title={`Edit ${type}`}
|
||||
className={styles["action"]}
|
||||
onClick={onClick && onClick}
|
||||
>
|
||||
<AiOutlineEdit />
|
||||
</LinkTag>
|
||||
);
|
||||
}
|
||||
31
src/components/QuickActions/FavoriteItem.tsx
Normal file
31
src/components/QuickActions/FavoriteItem.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { ReactNode, useState } from "react";
|
||||
import { AiFillStar, AiOutlineStar } from "react-icons/ai";
|
||||
|
||||
export default function FavoriteItem({
|
||||
isFavorite,
|
||||
children,
|
||||
onClick,
|
||||
}: {
|
||||
isFavorite: boolean;
|
||||
children?: ReactNode;
|
||||
onClick?: (event: any) => void; // FIXME: find good event type
|
||||
}) {
|
||||
const starColor = "#ffc107";
|
||||
const [isItemFavorite, setFavorite] = useState<boolean>(isFavorite);
|
||||
|
||||
const handleClick = (event) => {
|
||||
onClick && onClick(event);
|
||||
setFavorite((v) => !v);
|
||||
};
|
||||
|
||||
return (
|
||||
<div onClick={handleClick}>
|
||||
{isItemFavorite ? (
|
||||
<AiFillStar color={starColor} />
|
||||
) : (
|
||||
<AiOutlineStar color={starColor} />
|
||||
)}
|
||||
{children && <>{children}</>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
27
src/components/QuickActions/RemoveItem.tsx
Normal file
27
src/components/QuickActions/RemoveItem.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import LinkTag from "next/link";
|
||||
import { CgTrashEmpty } from "react-icons/cg";
|
||||
|
||||
import { Category, Link } from "types";
|
||||
|
||||
import styles from "./quickactions.module.scss";
|
||||
|
||||
export default function RemoveItem({
|
||||
type,
|
||||
id,
|
||||
onClick,
|
||||
}: {
|
||||
type: "category" | "link";
|
||||
id: Link["id"] | Category["id"];
|
||||
onClick?: (event: any) => void; // FIXME: find good event type
|
||||
}) {
|
||||
return (
|
||||
<LinkTag
|
||||
href={`/${type}/remove/${id}`}
|
||||
title={`Remove ${type}`}
|
||||
className={styles["action"]}
|
||||
onClick={onClick && onClick}
|
||||
>
|
||||
<CgTrashEmpty color="red" />
|
||||
</LinkTag>
|
||||
);
|
||||
}
|
||||
18
src/components/QuickActions/quickactions.module.scss
Normal file
18
src/components/QuickActions/quickactions.module.scss
Normal file
@@ -0,0 +1,18 @@
|
||||
.action {
|
||||
border: 0 !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& svg {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
transition: 0.15s;
|
||||
}
|
||||
|
||||
&:hover svg {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import LinkTag from "next/link";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { AiFillDelete, AiFillEdit } from "react-icons/ai";
|
||||
|
||||
import { Category } from "types";
|
||||
|
||||
import EditItem from "components/QuickActions/EditItem";
|
||||
import RemoveItem from "components/QuickActions/RemoveItem";
|
||||
|
||||
import styles from "./categories.module.scss";
|
||||
|
||||
interface CategoryItemProps {
|
||||
@@ -45,20 +46,12 @@ export default function CategoryItem({
|
||||
function MenuOptions({ id }: { id: number }): JSX.Element {
|
||||
return (
|
||||
<div className={styles["menu-item"]}>
|
||||
<LinkTag
|
||||
href={`/category/edit/${id}`}
|
||||
className={styles["option-edit"]}
|
||||
<EditItem
|
||||
type="category"
|
||||
id={id}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
<AiFillEdit />
|
||||
</LinkTag>
|
||||
<LinkTag
|
||||
href={`/category/remove/${id}`}
|
||||
className={styles["option-remove"]}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
<AiFillDelete color="red" />
|
||||
</LinkTag>
|
||||
/>
|
||||
<RemoveItem type="category" id={id} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user