refactor: Made modal a reusable component
All checks were successful
Deploy Brew Application / deploy (push) Successful in 11s
All checks were successful
Deploy Brew Application / deploy (push) Successful in 11s
This commit is contained in:
@@ -1,108 +1,33 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import Modal from "./Modal";
|
||||
|
||||
export default function CreateModal({ onClose, onAddBean, onAddBrew }) {
|
||||
const [active, setActive] = useState(false);
|
||||
const [dragY, setDragY] = useState(0);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [startY, setStartY] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
// Prevent background scroll when mounted
|
||||
document.body.style.overflow = "hidden";
|
||||
// Trigger transition shortly after mounting
|
||||
const raf = requestAnimationFrame(() => setActive(true));
|
||||
return () => {
|
||||
cancelAnimationFrame(raf);
|
||||
document.body.style.overflow = "";
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleClose = (callback) => {
|
||||
setActive(false);
|
||||
setTimeout(() => {
|
||||
onClose();
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
}, 200);
|
||||
};
|
||||
|
||||
const handleDragStart = (clientY) => {
|
||||
setIsDragging(true);
|
||||
setStartY(clientY);
|
||||
};
|
||||
|
||||
const handleDragMove = (clientY) => {
|
||||
if (!isDragging) return;
|
||||
const deltaY = clientY - startY;
|
||||
if (deltaY > 0) {
|
||||
setDragY(deltaY);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDragEnd = () => {
|
||||
if (!isDragging) return;
|
||||
setIsDragging(false);
|
||||
if (dragY > 100) {
|
||||
handleClose();
|
||||
} else {
|
||||
setDragY(0);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`fixed inset-0 bg-[rgba(44,24,16,0.5)] z-[100] flex items-end justify-center transition-opacity duration-200 ease-in-out ${active ? "opacity-100" : "opacity-0"}`}
|
||||
onClick={() => handleClose()}
|
||||
>
|
||||
<div
|
||||
className={`bg-[#FAF6F1] dark:bg-[#150B07] rounded-t-[28px] w-full max-w-[480px] px-5 pb-10 transition-transform duration-200 ease-in-out`}
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{
|
||||
transform: isDragging
|
||||
? `translateY(${dragY}px)`
|
||||
: active
|
||||
? `translateY(${dragY}px)`
|
||||
: "translateY(100%)",
|
||||
transition: isDragging ? "none" : "transform 0.2s ease-out"
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="w-full py-4 -mt-2 cursor-grab active:cursor-grabbing flex justify-center select-none"
|
||||
onTouchStart={(e) => handleDragStart(e.touches[0].clientY)}
|
||||
onTouchMove={(e) => handleDragMove(e.touches[0].clientY)}
|
||||
onTouchEnd={handleDragEnd}
|
||||
onMouseDown={(e) => handleDragStart(e.clientY)}
|
||||
onMouseMove={(e) => {
|
||||
if (e.buttons === 1) handleDragMove(e.clientY);
|
||||
}}
|
||||
onMouseUp={handleDragEnd}
|
||||
onMouseLeave={handleDragEnd}
|
||||
>
|
||||
<div className="w-9 h-1 bg-[#E8DFD3] dark:bg-[#3B2217] rounded" />
|
||||
</div>
|
||||
<div className="font-serif text-xl font-semibold text-[#2C1810] dark:text-[#FAF6F1] mb-6">What would you like to add?</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<button
|
||||
className="flex items-center gap-4 px-5 py-4 bg-white dark:bg-[#22120B] border border-[#E8DFD3] dark:border-[#3B2217] rounded-2xl text-left cursor-pointer hover:shadow-[0_4px_16px_rgba(44,24,16,0.08)] dark:hover:shadow-[0_4px_16px_rgba(0,0,0,0.3)] transition-all active:scale-[0.98]"
|
||||
onClick={() => handleClose(onAddBrew)}>
|
||||
<div className="w-12 h-12 rounded-xl bg-[#FAF6F1] dark:bg-[#2C1810] flex items-center justify-center text-2xl flex-shrink-0">☕</div>
|
||||
<div>
|
||||
<div className="font-semibold text-[#2C1810] dark:text-[#FAF6F1] text-sm">Log a Brew</div>
|
||||
<div className="text-xs text-[#9C8B7A] dark:text-[#C8B9A6] mt-0.5">Record a brewing session with recipe details</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
className="flex items-center gap-4 px-5 py-4 bg-white dark:bg-[#22120B] border border-[#E8DFD3] dark:border-[#3B2217] rounded-2xl text-left cursor-pointer hover:shadow-[0_4px_16px_rgba(44,24,16,0.08)] dark:hover:shadow-[0_4px_16px_rgba(0,0,0,0.3)] transition-all active:scale-[0.98]"
|
||||
onClick={() => handleClose(onAddBean)}>
|
||||
<div className="w-12 h-12 rounded-xl bg-[#FAF6F1] dark:bg-[#2C1810] flex items-center justify-center text-2xl flex-shrink-0">🫘</div>
|
||||
<div>
|
||||
<div className="font-semibold text-[#2C1810] dark:text-[#FAF6F1] text-sm">Add Bean</div>
|
||||
<div className="text-xs text-[#9C8B7A] dark:text-[#C8B9A6] mt-0.5">Add a new coffee bean to your library</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Modal onClose={onClose} padding="px-5 pb-10">
|
||||
{(close) => (
|
||||
<>
|
||||
<div className="font-serif text-xl font-semibold text-[#2C1810] dark:text-[#FAF6F1] mb-6">What would you like to add?</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<button
|
||||
className="flex items-center gap-4 px-5 py-4 bg-white dark:bg-[#22120B] border border-[#E8DFD3] dark:border-[#3B2217] rounded-2xl text-left cursor-pointer hover:shadow-[0_4px_16px_rgba(44,24,16,0.08)] dark:hover:shadow-[0_4px_16px_rgba(0,0,0,0.3)] transition-all active:scale-[0.98]"
|
||||
onClick={() => close(onAddBrew)}>
|
||||
<div className="w-12 h-12 rounded-xl bg-[#FAF6F1] dark:bg-[#2C1810] flex items-center justify-center text-2xl flex-shrink-0">☕</div>
|
||||
<div>
|
||||
<div className="font-semibold text-[#2C1810] dark:text-[#FAF6F1] text-sm">Log a Brew</div>
|
||||
<div className="text-xs text-[#9C8B7A] dark:text-[#C8B9A6] mt-0.5">Record a brewing session with recipe details</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
className="flex items-center gap-4 px-5 py-4 bg-white dark:bg-[#22120B] border border-[#E8DFD3] dark:border-[#3B2217] rounded-2xl text-left cursor-pointer hover:shadow-[0_4px_16px_rgba(44,24,16,0.08)] dark:hover:shadow-[0_4px_16px_rgba(0,0,0,0.3)] transition-all active:scale-[0.98]"
|
||||
onClick={() => close(onAddBean)}>
|
||||
<div className="w-12 h-12 rounded-xl bg-[#FAF6F1] dark:bg-[#2C1810] flex items-center justify-center text-2xl flex-shrink-0">🫘</div>
|
||||
<div>
|
||||
<div className="font-semibold text-[#2C1810] dark:text-[#FAF6F1] text-sm">Add Bean</div>
|
||||
<div className="text-xs text-[#9C8B7A] dark:text-[#C8B9A6] mt-0.5">Add a new coffee bean to your library</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user