Skip to content

Commit

Permalink
Add Caregiver Baby Book Main Pages & Update Admin Baby Book Page (#144)
Browse files Browse the repository at this point in the history
* Add caregiver baby book & styles for admin

* update admin album page

* minor design fixes on admin book page

* small little refactor for readability-n

* Clean up code for boss

* Add image upload backend and TODO notes
  • Loading branch information
tsar-boomba authored Oct 3, 2024
1 parent f45230a commit f01faca
Show file tree
Hide file tree
Showing 18 changed files with 728 additions and 120 deletions.
90 changes: 78 additions & 12 deletions web/components/BabyBook/PictureArray.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import ArrowUpIcon from "@components/Icons/LeftChevronIcon copy";
import { UseMapWrapper } from "@lib/hooks/useMap";
import { monthIndexToString } from "@lib/utils/date";
import Image from "next/image";
import { useRouter } from "next/router";
import { BabyBookYear, BabyImage } from "pages/admin/book/[babyId]";
import React, { useEffect, useRef, useState } from "react";

const PictureArray = ({ babyBook, select }: Props) => {
const selectedForDownloadKey = (i: number, j: number, k: number) =>
`${i}${j}${k}`;

const PictureArray = ({ babyBook, select, selectedForDownload }: Props) => {
const router = useRouter();
const wrapper = useRef<HTMLDivElement>(null);
const [showToTop, setShowToTop] = useState(false);
Expand All @@ -14,6 +18,7 @@ const PictureArray = ({ babyBook, select }: Props) => {
year.months.map((_) => React.createRef<HTMLDivElement>())
)
);

useEffect(() => {
const onHashChange = (
url = window.location.pathname + window.location.hash
Expand Down Expand Up @@ -53,6 +58,7 @@ const PictureArray = ({ babyBook, select }: Props) => {
if (scrollTop > 0) setShowToTop(true);
else setShowToTop(false);
};

const toTop = () => {
if (!wrapper.current) return;
wrapper.current.scrollTop = 0;
Expand All @@ -69,19 +75,63 @@ const PictureArray = ({ babyBook, select }: Props) => {
<div key={year.year} className="mb-10">
<h1 className="text-3xl font-semibold mb-4">{year.year}</h1>
{year.months.map((month, j) => {
const monthSelected = month.images.every((_, k) =>
selectedForDownload.has(selectedForDownloadKey(i, j, k))
);

return (
<div key={month.month} ref={refs.current[i][j]}>
<h2 className="font-semibold mb-2">
{monthIndexToString(month.month)} {year.year}
<h2
className="group flex items-center font-semibold mb-2 cursor-pointer"
onClick={() => {
selectedForDownload.batch((map) => {
month.images.forEach((img, k) => {
const key = selectedForDownloadKey(i, j, k);
if (monthSelected) {
map.delete(key);
} else {
map.set(key, img);
}
});
});
}}
>
<input
type="checkbox"
checked={monthSelected}
className={`hidden mr-2 w-6 h-6 group-hover:block ${monthSelected ? "!block" : ""}`}
/>
<span>
{monthIndexToString(month.month)} {year.year}
</span>
</h2>
<div className="flex flex-wrap">
{month.images.map((image, k) => (
<BabyBookImage
image={image}
onClick={() => select(i, j, k)}
key={k}
/>
))}
{month.images.map((image, k) => {
const imageSelected = selectedForDownload.has(
selectedForDownloadKey(i, j, k)
);

return (
<BabyBookImage
image={image}
onClick={() => select(i, j, k)}
selected={imageSelected}
onCheckboxClick={() => {
if (imageSelected) {
selectedForDownload.delete(
selectedForDownloadKey(i, j, k)
);
} else {
selectedForDownload.set(
selectedForDownloadKey(i, j, k),
image
);
}
}}
key={k}
/>
);
})}
</div>
</div>
);
Expand All @@ -104,28 +154,44 @@ const PictureArray = ({ babyBook, select }: Props) => {
const BabyBookImage = ({
image,
onClick,
onCheckboxClick,
selected,
}: {
image: BabyImage;
onClick: () => void;
selected: boolean;
onCheckboxClick: () => void;
}) => {
const borderClasses = `border hover:border-mbb-pink ${selected ? "!border-mbb-pink" : ""}`;

return (
<div
className="w-[200px] h-[300px] overflow-hidden relative shadow-lg rounded mx-3 my-3 cursor-pointer"
className={`group w-[200px] h-[300px] overflow-hidden relative shadow-lg rounded mx-3 my-3 cursor-pointer ${borderClasses}`}
onClick={onClick}
>
<Image src={image.imageUrl} layout={"fill"} objectFit={"cover"} />
{image.caption && (
<p className="absolute bottom-0 line-clamp-3 text-ellipsis bg-white w-full min-h-[4rem] p-2">
<p className="absolute bottom-0 left-0 right-0 line-clamp-3 text-ellipsis bg-white min-h-[4rem] p-3">
{image.caption}
</p>
)}
<input
type="checkbox"
checked={selected}
className={`absolute hidden top-2 left-2 w-6 h-6 group-hover:block ${selected ? "!block" : ""}`}
onClick={(e) => {
e.stopPropagation();
onCheckboxClick();
}}
/>
</div>
);
};

interface Props {
babyBook: BabyBookYear[];
select: (arg0: number, arg1: number, arg2: number) => void;
selectedForDownload: UseMapWrapper<string, BabyImage>;
}

export default PictureArray;
16 changes: 8 additions & 8 deletions web/components/BabyBook/PictureModal.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Button from "@components/atoms/Button";
import DownloadIcon from "@components/Icons/DownloadIcon";
import LeftChevronIcon from "@components/Icons/LeftChevronIcon";
import RightChevronIcon from "@components/Icons/RightChevronIcon";
Expand Down Expand Up @@ -37,13 +38,13 @@ const PictureModal = ({
).toDate();
return (
<div className="absolute flex flex-col align-center w-full h-full bg-white">
<div className="flex mt-8 ml-8 text-highlight font-semibold">
<div className="flex mt-8 ml-8 text-mbb-pink font-semibold">
<div
className="flex cursor-pointer items-center"
onClick={() => deselect()}
>
<LeftChevronIcon />
<p className="ml-2">Download</p>
<p className="ml-2">Back to album</p>
</div>
</div>
<div className="flex w-full justify-between flex-grow p-4">
Expand Down Expand Up @@ -90,13 +91,12 @@ const PictureModal = ({
<p className="my-4">
{image.caption === "" ? "No Caption" : image.caption}
</p>
<button
<Button
onClick={downloadImage}
className="rounded px-4 py-2 border border-highlight flex items-center text-highlight"
>
<DownloadIcon />
<p className="ml-2">Download</p>
</button>
text="Download"
icon={<DownloadIcon />}
width="auto"
/>
</div>
</div>
</div>
Expand Down
12 changes: 6 additions & 6 deletions web/components/BabyBook/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const SideBar = ({ babyBook }: Props) => {

return (
<div className="overflow-auto shrink-0">
<div className="w-[164px] flex flex-col items-end pt-8 text-dark-400 overflow-hidden">
<div className="w-[164px] flex flex-col items-stretch pt-8 text-dark-400 overflow-hidden">
{babyBook.map((year) => (
<YearSection
key={year.year}
Expand Down Expand Up @@ -104,27 +104,27 @@ const YearSection = ({
};

return (
<div className="w-full flex flex-col items-end">
<div className="w-full flex flex-col items-stretch">
<p
onClick={() => setIsExpanded(!isExpanded)}
className={`font-semibold text-lg border-r px-4 cursor-pointer ${
className={`font-semibold text-lg border-r px-4 cursor-pointer text-end ${
year === currentYear ? "text-black" : ""
}`}
>
{year}
</p>
<div
className={`flex flex-col text-right w-full ${
className={`flex flex-col items-stretch text-right w-full ${
isExpanded ? "" : "hidden"
}`}
>
{months.map((month) => (
<p
key={month.month}
onClick={() => pushHash(`${year}.${month.month}`)}
className={`p-1 px-8 w-full border-r cursor-pointer ${
className={`p-1 px-8 border-r cursor-pointer ${
month.month === currentMonth
? "bg-alt border-r-[3px] border-highlight text-black"
? "bg-mbb-pink/10 border-r-[3px] border-mbb-pink text-black"
: ""
}`}
>
Expand Down
80 changes: 38 additions & 42 deletions web/components/BabyBook/Topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@ import DownloadIcon from "@components/Icons/DownloadIcon";
import ImageIcon from "@components/Icons/ImageIcon";
import LinkIcon from "@components/Icons/LinkIcon";
import PersonIcon from "@components/Icons/PersonIcon";
import { GetServerSideProps } from "next";
import Image from "next/image";
import { stringify } from "querystring";
import { useState } from "react";
import admin_portal_gradient from "../../public/admin_portal_gradient.png";
import left_heart from "../../public/left_heart.png";
import right_heart from "../../public/right_heart.png";
import Button from "@components/atoms/Button";
import Image from "next/image";

const TopBar = ({ number, motherName, name, content, iv }: Props) => {
const TopBar = ({
number,
motherName,
name,
content,
iv,
isPictureSelected,
}: Props) => {
const [copiedConfirmation, setCopiedConfirmation] = useState(false);

const downloadAlbum = async () => {
const downloadAlbum = () => {
const a = document.createElement("a");
a.href = `/api/download-album?content=${content}&iv=${iv}`;
console.log(a.href);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
Expand All @@ -35,22 +37,17 @@ const TopBar = ({ number, motherName, name, content, iv }: Props) => {
return (
<div className="flex justify-between w-full shadow-lg">
<div className="flex items-center">
<div className="w-[164px] h-[81px] overflow-hidden">
<div className="relative right-12">
<Image
className="relative"
layout="fixed"
src={admin_portal_gradient}
/>
</div>
<div className="flex items-center justify-center min-w-[164px] h-[81px] overflow-hidden bg-admin-baby-book-background">
<Image
src="/MBBLogo.svg"
alt="Motherhood Beyond Bars Logo"
height={40}
width={41}
/>
</div>
<span className="absolute top-[26px] left-[67px]">
<Image className="static px-10" src={left_heart} />
</span>
<span className="absolute top-[26px] left-[83px]">
<Image className="static px-10" src={right_heart} />
</span>
<p className="font-bold text-2xl text-center mx-4">{name}'s album</p>
<p className="font-bold text-2xl text-center mx-4">
{name}&apos;s album
</p>
<div className="flex items-center mx-3">
<ImageIcon />
<p className="text-dark-400 ml-1">{number} photos</p>
Expand All @@ -60,24 +57,22 @@ const TopBar = ({ number, motherName, name, content, iv }: Props) => {
<p className="text-dark-400 ml-1">Mother - {motherName}</p>
</div>
</div>
<div className="flex items-center font-semibold text-highlight">
<button
className="rounded px-4 py-2 border border-highlight mx-2 flex items-center cursor-pointer"
onClick={downloadAlbum}
>
<DownloadIcon />
<p className="ml-2">Download album</p>
</button>
<button
className="rounded px-4 py-2 border border-highlight mx-2 flex items-center cursor-pointer"
onClick={copyLink}
>
<LinkIcon />
<p className="ml-2">
{copiedConfirmation ? "Copied!" : "Copy album link"}
</p>
</button>
</div>
{!isPictureSelected && (
<div className="flex items-center gap-[1.125rem] mr-6">
<Button
onClick={downloadAlbum}
text="Download album"
icon={<DownloadIcon />}
width="auto"
/>
<Button
onClick={copyLink}
text="Copy link"
icon={<LinkIcon />}
width="auto"
/>
</div>
)}
</div>
);
};
Expand All @@ -88,6 +83,7 @@ interface Props {
name: string;
content: string;
iv: string;
isPictureSelected: boolean;
}

export default TopBar;
3 changes: 1 addition & 2 deletions web/components/Icons/DownloadIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ const DownloadIcon = () => {
width="10"
height="14"
viewBox="0 0 10 14"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.46967 9.7803C4.76256 10.0732 5.23744 10.0732 5.53033 9.7803L9.2803 6.03033C9.5732 5.73744 9.5732 5.26256 9.2803 4.96967C8.9874 4.67678 8.5126 4.67678 8.2197 4.96967L5.75 7.43934V0.75C5.75 0.33579 5.41421 0 5 0C4.58579 0 4.25 0.33579 4.25 0.75V7.43934L1.78033 4.96967C1.48744 4.67678 1.01256 4.67678 0.71967 4.96967C0.42678 5.26256 0.42678 5.73744 0.71967 6.03033L4.46967 9.7803ZM0.75 12.0001C0.33579 12.0001 0 12.3359 0 12.7501C0 13.1643 0.33579 13.5001 0.75 13.5001H9.25C9.6642 13.5001 10 13.1643 10 12.7501C10 12.3359 9.6642 12.0001 9.25 12.0001H0.75Z"
fill="#304CD1"
/>
</svg>
);
Expand Down
3 changes: 1 addition & 2 deletions web/components/Icons/LinkIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ const LinkIcon = () => {
width="14"
height="14"
viewBox="0 0 14 14"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.77518 2.27518C6.6427 2.41735 6.57057 2.6054 6.574 2.7997C6.57743 2.994 6.65614 3.17938 6.79355 3.3168C6.93097 3.45421 7.11635 3.53292 7.31065 3.53635C7.50495 3.53978 7.693 3.46766 7.83518 3.33518L9.08518 2.08518C9.27098 1.89936 9.49158 1.75195 9.73438 1.65139C9.97718 1.55082 10.2374 1.49906 10.5002 1.49906C10.763 1.49906 11.0232 1.55082 11.266 1.65139C11.5088 1.75195 11.7294 1.89936 11.9152 2.08518C12.101 2.271 12.2484 2.4916 12.349 2.73438C12.4495 2.97717 12.5013 3.23739 12.5013 3.50018C12.5013 3.76297 12.4495 4.02318 12.349 4.26597C12.2484 4.50875 12.101 4.72935 11.9152 4.91518L9.41518 7.41518C9.22938 7.60113 9.00888 7.74865 8.76606 7.84929C8.52326 7.94994 8.26301 8.00175 8.00018 8.00175C7.73734 8.00175 7.47709 7.94994 7.23429 7.84929C6.9915 7.74865 6.77092 7.60113 6.58518 7.41518C6.443 7.2827 6.25495 7.21057 6.06065 7.214C5.86635 7.21743 5.68097 7.29614 5.54355 7.43355C5.40614 7.57097 5.32743 7.75635 5.324 7.95065C5.32057 8.14495 5.3927 8.333 5.52518 8.47518C5.85019 8.80022 6.23604 9.05808 6.6607 9.23398C7.08536 9.40988 7.54052 9.50038 8.00018 9.50038C8.45983 9.50038 8.91499 9.40988 9.33968 9.23398C9.76428 9.05808 10.1502 8.80022 10.4752 8.47518L12.9752 5.97518C13.6316 5.31876 14.0004 4.42848 14.0004 3.50018C14.0004 2.57187 13.6316 1.68159 12.9752 1.02518C12.3188 0.368763 11.4285 0 10.5002 0C9.57188 0 8.68159 0.368763 8.02517 1.02518L6.77518 2.27518ZM2.08518 11.9152C1.89922 11.7294 1.7517 11.5089 1.65106 11.2661C1.55041 11.0233 1.4986 10.763 1.4986 10.5002C1.4986 10.2374 1.55041 9.97708 1.65106 9.73428C1.7517 9.49148 1.89922 9.27088 2.08518 9.08518L4.58518 6.58518C4.77092 6.39922 4.9915 6.2517 5.23429 6.15106C5.47709 6.05041 5.73734 5.9986 6.00018 5.9986C6.26301 5.9986 6.52326 6.05041 6.76606 6.15106C7.00885 6.2517 7.22943 6.39922 7.41518 6.58518C7.55735 6.71766 7.7454 6.78978 7.9397 6.78635C8.134 6.78292 8.31938 6.70421 8.4568 6.5668C8.59421 6.42938 8.67292 6.244 8.67635 6.0497C8.67978 5.8554 8.60766 5.66735 8.47518 5.52518C8.15017 5.20013 7.76431 4.94229 7.33965 4.76638C6.91499 4.59047 6.45983 4.49992 6.00018 4.49992C5.54052 4.49992 5.08536 4.59047 4.6607 4.76638C4.23604 4.94229 3.85019 5.20013 3.52518 5.52518L1.02518 8.02517C0.368763 8.68159 0 9.57188 0 10.5002C0 11.4285 0.368763 12.3188 1.02518 12.9752C1.68159 13.6316 2.57187 14.0004 3.50018 14.0004C4.42848 14.0004 5.31876 13.6316 5.97518 12.9752L7.22518 11.7252C7.35766 11.583 7.42978 11.395 7.42635 11.2007C7.42292 11.0064 7.34421 10.821 7.2068 10.6836C7.06938 10.5462 6.884 10.4674 6.6897 10.464C6.4954 10.4606 6.30735 10.5327 6.16518 10.6652L4.91518 11.9152C4.72943 12.1011 4.50885 12.2487 4.26606 12.3493C4.02326 12.45 3.76301 12.5018 3.50018 12.5018C3.23734 12.5018 2.97709 12.45 2.73429 12.3493C2.4915 12.2487 2.27092 12.1011 2.08518 11.9152Z"
fill="#304CD1"
/>
</svg>
);
Expand Down
Loading

0 comments on commit f01faca

Please sign in to comment.