Skip to content

Commit

Permalink
trash can view
Browse files Browse the repository at this point in the history
  • Loading branch information
damarizz committed Dec 3, 2024
1 parent 7c7c4a3 commit 8f49a32
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 249 deletions.
2 changes: 1 addition & 1 deletion app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"prettier:write": "prettier --write \"**/*.{ts,tsx}\""
},
"dependencies": {
"@mantine/core": "7.14.2",
"@mantine/core": "^7.14.2",
"@mantine/form": "^7.14.2",
"@mantine/hooks": "^7.14.2",
"@mantine/notifications": "^7.14.2",
Expand Down
251 changes: 234 additions & 17 deletions app/src/pages/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from "react";
import { Menu, Search, Plus, Layout, Edit, Copy, Check } from "lucide-react";
import { Link } from "wouter";
import { useEffect, useState } from "react";
import { Menu, Search, Plus, Copy, Check, Trash, SkipBack, ChevronLeft } from "lucide-react";
import { Link, Route } from "wouter";
import { Box, Button, Loader, Modal, ScrollArea, Text, Title } from "@mantine/core";
import { NewGalleryForm } from "@/pages/Dashboard/components/NewGalleryForm";
import { useUser } from "@/stores/useUser";
Expand All @@ -13,6 +13,176 @@ import { UserButton } from "@/components/UserButton";
import { useApi } from "@/hooks/useApi";
import { StillerGallery } from "@/types";
import { thumbnailSrcFromTemplateId } from "@/utils";
import { set } from "zod";

export const TrashView = () => {
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const [sharePopupOpen, setSharePopupOpen] = useState(false);
const [deletePopupOpen, setDeletePopupOpen] = useState(false);
const [currentGallerySlug, setCurrentGallerySlug] = useState("");
const [isModalOpen, setIsModalOpen] = useState(false);
const [deletedGalleries, setDeletedGalleries] = useState<StillerGallery[]>([]);
const { user, loading } = useUser();
const [selectedGallery, setSelectedGallery] = useState<StillerGallery | null>(null);


const { response: initialUserGalleries, isLoading: galleryLoading } = useApi<StillerGallery[]>('/gallery');

useEffect(() => {
if (initialUserGalleries?.data) {
setDeletedGalleries(initialUserGalleries.data);
}
}, [initialUserGalleries]);

const toggleSidebar = () => {
setIsSidebarOpen(!isSidebarOpen);
};

const handleRestoreGallery = (gallery: StillerGallery) => {
const updatedDeletedGalleries = deletedGalleries.filter(g => g.id !== gallery.id);
setDeletedGalleries(updatedDeletedGalleries);
};

const handlePermanentDelete = (gallery: StillerGallery) => {
const updatedDeletedGalleries = deletedGalleries.filter(g => g.id !== gallery.id);
setDeletedGalleries(updatedDeletedGalleries);
};

if (!user || loading) {
return <LoadingScreen />;
}

return (
<ScrollArea className={styles.container}>
{isSidebarOpen && (
<div
className={styles.overlay}
onClick={toggleSidebar}
/>
)}
<div
className={`${styles.sidebar} ${isSidebarOpen ? styles.sidebarOpen : ""}`}
>
<div className={styles.sidebarContent}>
<h2 className={styles.sidebarTitle}>Menú</h2>
<nav className={styles.sidebarNav}>
<button
className={styles.sidebarButton}
onClick={() => setIsModalOpen(true)}
>
<Plus className={styles.sidebarIcon} />
<span>Nueva Galería</span>
</button>
<button onClick={() => window.location.href = "/"} className={styles.sidebarButton}>
<ChevronLeft className={styles.sidebarIcon} />
<span>Volver al Dashboard</span>
</button>
</nav>
</div>
</div>

<header className={styles.header}>
<div className={styles.headerContent}>
<button onClick={toggleSidebar} className={styles.menuButton}>
<Menu className={styles.menuIcon} />
<span className={styles.srOnly}>Papelera</span>
</button>
<div style={{ display: 'flex', gap: '24px' }}>
<NewGalleryButton />
<UserButton />
</div>
</div>
</header>

<main className={styles.main}>
<div className={styles.profileSection}>
<h1 className={styles.profileName}>Papelera</h1>
<p className={styles.profileDescription}>Galerías eliminadas (se borrarán en 30 días)</p>
</div>

{galleryLoading && (
<Box mt={72} display={'flex'} style={{ justifyContent: 'center' }}>
<Loader size={30} />
</Box>
)}

{deletedGalleries.length === 0 && (
<Box mt={72} display={'flex'} style={{ alignItems: 'center', flexDirection: 'column', gap: 18 }}>
<Title order={5}>No hay galerías en la papelera 🗑️</Title>
</Box>
)}

<div className={styles.galleryGrid}>
{deletedGalleries.map((gallery) => (
<div
key={gallery.id}
className={styles.galleryCard}
>
<img
src={thumbnailSrcFromTemplateId(gallery.templateid)}
alt={gallery.title}
className={styles.galleryImage}
/>
<div className={styles.galleryOverlay}>
<h2 className={styles.galleryTitle}>{gallery.title}</h2>
<p className={styles.galleryDescription}>
{gallery.description}
</p>
<div className={styles.galleryActions}>
<button
onClick={() => handleRestoreGallery(gallery)}
className={styles.openButton}
aria-label="Restaurar"
>
<SkipBack size={16} /> Restaurar
</button>
<button
onClick={() => {
setSelectedGallery(gallery);
setDeletePopupOpen(true);
}}
className={styles.shareButton}
aria-label="Eliminar"
>
Eliminar
</button>
</div>
</div>
</div>
))}
</div>
</main>
<DeleteGalleryPopUp
trigger={deletePopupOpen}
setTrigger={setDeletePopupOpen}
onConfirm={() => {
if (selectedGallery) {
const updatedDeletedGalleries = deletedGalleries.filter(g => g.id !== selectedGallery.id);
setDeletedGalleries(updatedDeletedGalleries);
setSelectedGallery(null);
}
}}
/>

<Modal
opened={isModalOpen}
onClose={() => setIsModalOpen(false)}
centered
withCloseButton={false}
size="auto"
overlayProps={{
backgroundOpacity: 0.55,
blur: 3,
}}
style={{
overflow: 'hidden',
}}
>
<NewGalleryForm modalKey={'new-gallery-modal'} />
</Modal>
</ScrollArea>
);
};

const ShareGalleryPopup = ({
trigger,
Expand Down Expand Up @@ -78,9 +248,41 @@ const ShareGalleryPopup = ({
);
};

const DeleteGalleryPopUp = ({
trigger,
setTrigger,
onConfirm,
}: {
trigger: boolean;
setTrigger: (value: boolean) => void;
onConfirm: () => void;
}) => {
return (
<Popup trigger={trigger} setTrigger={() => setTrigger(false)}>
<h4 className={popupStyles.title}>¿Quieres borrar esta galería?</h4>
<p className={popupStyles.description}>
Será enviada a la papelera, donde permanecerá por 30 días.
</p>
<div style={{ display: "flex", justifyContent: "space-between", gap: "10px", marginTop: "20px" }}>
<button
className={popupStyles.button}
onClick={() => window.location.href = "/trash"}
>
</button>
<button className={popupStyles.button} onClick={() => setTrigger(false)}>
No
</button>
</div>
</Popup>
);
};


export const GalleryDashboard = () => {
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const [sharePopupOpen, setSharePopupOpen] = useState(false);
const [deletePopupOpen, setDeletePopupOpen] = useState(false);
const [currentGallerySlug, setCurrentGallerySlug] = useState("");
const [isModalOpen, setIsModalOpen] = useState(false);
const [showCommunityProjects, setShowCommunityProjects] = useState(false);
Expand All @@ -98,12 +300,17 @@ export const GalleryDashboard = () => {
setSharePopupOpen(true);
};

const handleDeleteGallery = () => {
setDeletePopupOpen(true);
};

if (!user || loading) {
return <LoadingScreen />;
}

return (
<ScrollArea className={styles.container}>
<Route path="/dashboard">
{isSidebarOpen && (
<div
className={styles.overlay}
Expand All @@ -122,19 +329,11 @@ export const GalleryDashboard = () => {
>
<Plus className={styles.sidebarIcon} />
<span>Nueva Galería</span>
</button>
<button
className={styles.sidebarButton}
>
<Layout className={styles.sidebarIcon} />
<span>Desplegar Galería</span>
</button>
<button
className={styles.sidebarButton}
>
<Edit className={styles.sidebarIcon} />
<span>Editar Galería</span>
</button>
</button>
<button onClick={() => window.location.href = "/trash"} className={styles.sidebarButton}>
<Trash className={styles.sidebarIcon} />
<span>Papelera</span>
</button>
</nav>
</div>
</div>
Expand Down Expand Up @@ -225,7 +424,7 @@ export const GalleryDashboard = () => {
</p>
<div className={styles.galleryActions}>
<Link
href={`/${gallery.slug}`}
href={`https://metagallery.pages.dev/${gallery.slug}`}
className={styles.openButton}
>
Visitar
Expand Down Expand Up @@ -262,12 +461,23 @@ export const GalleryDashboard = () => {
>
Compartir
</button>
<button
onClick={() => handleDeleteGallery()}
className={styles.deleteButton}
aria-label="Delete gallery">
<Trash size={16} />
</button>
</div>
</div>
</div>
))}
</div>
</main>
</Route>

<Route path="/trash">
<TrashView />
</Route>

<Modal
opened={isModalOpen}
Expand All @@ -291,6 +501,13 @@ export const GalleryDashboard = () => {
setTrigger={setSharePopupOpen}
gallerySlug={currentGallerySlug}
/>
<DeleteGalleryPopUp
trigger={deletePopupOpen}
setTrigger={setDeletePopupOpen}
onConfirm={() => {
// ...
}}
/>
</ScrollArea>
);
};
22 changes: 22 additions & 0 deletions app/src/pages/Dashboard/GalleryDashboard.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
background: none;
border: none;
cursor: pointer;
text-decoration: none;
color: black;
}

.menuButton:hover {
Expand Down Expand Up @@ -285,6 +287,26 @@
gap: 0.5rem;
}

.deleteButton {
background: none;
border: none;
cursor: pointer;
color: white;
padding: 5px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s;
position: absolute;
bottom: 15px;
right: 15px;
}

.deleteButton:hover {
background-color: rgba(255, 255, 255, 0.2);
}

.openButton,
.shareButton {
padding: 0.25rem 1rem;
Expand Down
Loading

0 comments on commit 8f49a32

Please sign in to comment.