From 8816c16c9ee3f5f91ae308eb5c65ce8c26d5df6c Mon Sep 17 00:00:00 2001 From: tsar-boomba Date: Sat, 28 Sep 2024 18:31:12 -0400 Subject: [PATCH 1/8] Add caregiver baby book & styles for admin --- web/components/BabyBook/PictureArray.tsx | 4 +- web/components/BabyBook/Sidebar.tsx | 12 +- web/components/BabyBook/Topbar.tsx | 53 +++--- web/components/Icons/DownloadIcon.tsx | 6 +- web/components/Icons/LinkIcon.tsx | 6 +- web/components/Icons/LockIcon.tsx | 36 ++++ web/components/Icons/PlusIcon.tsx | 18 ++ web/components/Icons/SmileIcon.tsx | 40 +++++ web/components/atoms/Button.tsx | 7 +- web/lib/utils/date.ts | 34 ++-- web/lib/utils/encryption.ts | 2 +- web/pages/admin/book/[babyId].tsx | 3 + web/pages/caregiver/book/[babyId].tsx | 218 +++++++++++++++++++++++ web/pages/caregiver/book/index.tsx | 101 +++++++++++ web/tailwind.config.js | 2 + 15 files changed, 481 insertions(+), 61 deletions(-) create mode 100644 web/components/Icons/LockIcon.tsx create mode 100644 web/components/Icons/PlusIcon.tsx create mode 100644 web/components/Icons/SmileIcon.tsx create mode 100644 web/pages/caregiver/book/[babyId].tsx create mode 100644 web/pages/caregiver/book/index.tsx diff --git a/web/components/BabyBook/PictureArray.tsx b/web/components/BabyBook/PictureArray.tsx index 15b01802..6dbecb37 100644 --- a/web/components/BabyBook/PictureArray.tsx +++ b/web/components/BabyBook/PictureArray.tsx @@ -14,6 +14,7 @@ const PictureArray = ({ babyBook, select }: Props) => { year.months.map((_) => React.createRef()) ) ); + useEffect(() => { const onHashChange = ( url = window.location.pathname + window.location.hash @@ -53,6 +54,7 @@ const PictureArray = ({ babyBook, select }: Props) => { if (scrollTop > 0) setShowToTop(true); else setShowToTop(false); }; + const toTop = () => { if (!wrapper.current) return; wrapper.current.scrollTop = 0; @@ -115,7 +117,7 @@ const BabyBookImage = ({ > {image.caption && ( -

+

{image.caption}

)} diff --git a/web/components/BabyBook/Sidebar.tsx b/web/components/BabyBook/Sidebar.tsx index f3eede36..d7b34da7 100644 --- a/web/components/BabyBook/Sidebar.tsx +++ b/web/components/BabyBook/Sidebar.tsx @@ -60,7 +60,7 @@ const SideBar = ({ babyBook }: Props) => { return (
-
+
{babyBook.map((year) => ( +

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}

@@ -122,9 +122,9 @@ const YearSection = ({

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" : "" }`} > diff --git a/web/components/BabyBook/Topbar.tsx b/web/components/BabyBook/Topbar.tsx index 073982a3..4e426f0e 100644 --- a/web/components/BabyBook/Topbar.tsx +++ b/web/components/BabyBook/Topbar.tsx @@ -9,6 +9,7 @@ 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"; const TopBar = ({ number, motherName, name, content, iv }: Props) => { const [copiedConfirmation, setCopiedConfirmation] = useState(false); @@ -35,22 +36,24 @@ const TopBar = ({ number, motherName, name, content, iv }: Props) => { return (

-
-
- + + -
+
- - - - - - -

{name}'s album

+

+ {name}'s album +

{number} photos

@@ -60,23 +63,13 @@ const TopBar = ({ number, motherName, name, content, iv }: Props) => {

Mother - {motherName}

-
- - + text="Download album" + icon={} + /> +
); diff --git a/web/components/Icons/DownloadIcon.tsx b/web/components/Icons/DownloadIcon.tsx index 69eddd67..8c607246 100644 --- a/web/components/Icons/DownloadIcon.tsx +++ b/web/components/Icons/DownloadIcon.tsx @@ -8,10 +8,10 @@ const DownloadIcon = () => { xmlns="http://www.w3.org/2000/svg" > ); diff --git a/web/components/Icons/LinkIcon.tsx b/web/components/Icons/LinkIcon.tsx index 764b4982..25c6dbef 100644 --- a/web/components/Icons/LinkIcon.tsx +++ b/web/components/Icons/LinkIcon.tsx @@ -8,10 +8,10 @@ const LinkIcon = () => { xmlns="http://www.w3.org/2000/svg" > ); diff --git a/web/components/Icons/LockIcon.tsx b/web/components/Icons/LockIcon.tsx new file mode 100644 index 00000000..3f1b7661 --- /dev/null +++ b/web/components/Icons/LockIcon.tsx @@ -0,0 +1,36 @@ +export default function LockIcon() { + return ( + + + + + + + ); +} diff --git a/web/components/Icons/PlusIcon.tsx b/web/components/Icons/PlusIcon.tsx new file mode 100644 index 00000000..39e78105 --- /dev/null +++ b/web/components/Icons/PlusIcon.tsx @@ -0,0 +1,18 @@ +export default function PlusIcon() { + return ( + + + + ); +} diff --git a/web/components/Icons/SmileIcon.tsx b/web/components/Icons/SmileIcon.tsx new file mode 100644 index 00000000..236d41f8 --- /dev/null +++ b/web/components/Icons/SmileIcon.tsx @@ -0,0 +1,40 @@ +export default function SmileIcon() { + return ( + + + + + + + ); +} diff --git a/web/components/atoms/Button.tsx b/web/components/atoms/Button.tsx index 1ee467ac..89b37f68 100644 --- a/web/components/atoms/Button.tsx +++ b/web/components/atoms/Button.tsx @@ -7,12 +7,14 @@ interface Props { submit?: boolean; icon?: React.ReactNode; disabled?: boolean; + width?: string | number; } export default function Button({ text, type = "primary", onClick, + width, submit = false, icon = undefined, disabled = false, @@ -26,9 +28,12 @@ export default function Button({ onClick={onClick} disabled={disabled} type={submit ? "submit" : "button"} + style={{ width }} > {icon ? {icon} : null} - {text} + + {text} + ); } diff --git a/web/lib/utils/date.ts b/web/lib/utils/date.ts index eac75215..ca7238ee 100644 --- a/web/lib/utils/date.ts +++ b/web/lib/utils/date.ts @@ -16,20 +16,22 @@ export function formatDate(date: string) { export function monthIndexToString(index: number | string) { const number = parseInt(index as string); - if (!isNaN(number) && (number < 0 || number > 11)) return "Not a Month"; - const INDEX_TO_MONTH: { [key: string]: string } = { - "0": "January", - "1": "February", - "2": "March", - "3": "April", - "4": "May", - "5": "June", - "6": "July", - "7": "August", - "8": "September", - "9": "October", - "10": "November", - "11": "December", - }; - return INDEX_TO_MONTH[index]; + if (isNaN(number) || number < 0 || number > 11) return "Not a Month"; + + const INDEX_TO_MONTH = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ] as const; + + return INDEX_TO_MONTH[number]; } diff --git a/web/lib/utils/encryption.ts b/web/lib/utils/encryption.ts index 96464eb0..c3512596 100644 --- a/web/lib/utils/encryption.ts +++ b/web/lib/utils/encryption.ts @@ -42,7 +42,7 @@ const decrypt = (hash: { iv: string; content: string }) => { decrpyted.set(updated, 0); decrpyted.set(final, updated.length); - return decrpyted.toString(); + return new TextDecoder().decode(decrpyted); }; export { encrypt, decrypt }; diff --git a/web/pages/admin/book/[babyId].tsx b/web/pages/admin/book/[babyId].tsx index f07da826..eae5fec7 100644 --- a/web/pages/admin/book/[babyId].tsx +++ b/web/pages/admin/book/[babyId].tsx @@ -59,11 +59,14 @@ export default function BabyBook({ if (i < 0 || i === babyBook.length) return; } } + selectImage(i, j, k); }; + const deselectImage = () => { setIsPictureSelected(false); }; + return (
+
+

+ {baby.firstName} {baby.lastName} + {baby.lastName[baby.lastName.length - 1] === "s" ? "'" : "'s"} Album +

+

Birthday: {baby.birthday}

+
+ {totImages === 0 ? ( + <> +
+ +
+

+ No Photos Yet +

+

+ Get started by adding a photo of {baby.firstName} here! +

+ + ) : ( + babyBook.flatMap(({ year, months }) => + months.map(({ month, images }) => ( +
+

+ {monthIndexToString(month)} {year} +

+
+ {images.map(({ imageUrl, date }) => ( + <> +
{ + // TODO: view single image + }} + > + {`Baby +
+ + ))} +
+
+ )) + ) + )} + +
+ ); +} + +interface Props { + babyBook: BabyBookYear[]; + totImages: number; + baby: { + firstName: string; + lastName: string; + mother: string; + birthday: string; + }; + content: string; + iv: string; +} + +export interface BabyBookYear { + year: number; + months: BabyBookMonth[]; +} + +export interface BabyBookMonth { + month: number; + images: BabyImage[]; +} + +export interface BabyImage { + caption: string; + date: { + seconds: number; + nanoseconds: number; + }; + imageUrl: string; + caregiverId: string; +} + +interface RawBabyImage { + caption: string; + date: Timestamp; + imageURL: string; + caregiverID: DocumentReference; +} + +export const getServerSideProps: GetServerSideProps< + Props, + { babyId?: string } +> = async ({ params, query }) => { + const props: Props = { + babyBook: [], + totImages: 0, + baby: { firstName: "", lastName: "", mother: "", birthday: "" }, + content: "", + iv: "", + }; + + if (!params || !params.babyId || !query.iv) return { props }; + + props.content = params?.babyId as string; + props.iv = query.iv as string; + const babyId = decrypt({ iv: query.iv as string, content: params.babyId }); + + const babyRef = doc(db, "babies", babyId); + const baby = await getDoc(babyRef); + const babyData = baby.data() as Baby; + + props.baby = { + firstName: babyData.firstName, + lastName: babyData.lastName, + mother: babyData.motherName, + birthday: babyData.dob.toString(), + }; + const babyBookRef = doQuery( + collection(db, `babies/${babyId}/book`), + orderBy("date", "desc") + ); + const babyBookDocs = await getDocs(babyBookRef); + babyBookDocs.docs.forEach((book) => { + props.totImages = props.totImages + 1; + const raw = book.data() as RawBabyImage; + const date = raw.date.toDate(); + + const currYear = date.getFullYear(); + if ( + props.babyBook.length < 1 || + props.babyBook[props.babyBook.length - 1].year !== currYear + ) + props.babyBook.push({ year: currYear, months: [] }); + const year = props.babyBook[props.babyBook.length - 1]; + + const currMonth = date.getMonth(); + if ( + year.months.length < 1 || + year.months[year.months.length - 1].month !== currMonth + ) + year.months.push({ month: currMonth, images: [] }); + year.months[year.months.length - 1].images.push({ + caption: raw.caption || "", + imageUrl: raw.imageURL, + caregiverId: raw.caregiverID?.id || "", + date: { + seconds: raw.date.seconds, + nanoseconds: raw.date.nanoseconds, + }, + }); + }); + + return { + props, + }; +}; diff --git a/web/pages/caregiver/book/index.tsx b/web/pages/caregiver/book/index.tsx new file mode 100644 index 00000000..648a4ac7 --- /dev/null +++ b/web/pages/caregiver/book/index.tsx @@ -0,0 +1,101 @@ +import Button from "@components/atoms/Button"; +import LockIcon from "@components/Icons/LockIcon"; +import { GetServerSideProps } from "next"; + +interface Props { + babies: any[]; + books: { name: string; birthday: string; bookLink: string }[]; +} + +export default function BabyBookHome({ babies, books }: Props) { + if (babies.length === 0) { + return ( +
+
+ +
+

+ Restricted Access +

+

+ Looks like your account is not assigned to a child yet! +
+
+ Once the child is in your care,{" "} + + contact us + {" "} + to set up account features for you and the child. +

+
+ ); + } + + if (books.length === 0) { + return ( +
+

+ Start a Baby Book +

+

+ The Baby Book is a place where you can document the baby's journey + by uploading images and descriptions. Motherhood Behind Bars will then + deliver the images to the mothers, so they can stay updated on their + baby's growth. +

+
+ ); + } + + return ( +
+

+ Current Baby Books +

+
+ {books.map(({ name, birthday, bookLink }) => ( + +

{name}

+

+ Birthday: {birthday} +

+
+ ))} +
+
+ ); +} + +export const getServerSideProps: GetServerSideProps = async ({ + query, +}) => { + // TODO: implement actual book fetching here + return { + props: { + babies: [""], + books: [ + { + name: "John", + birthday: "11/13/2204", + bookLink: + "/caregiver/book/bd89888ca382e490a04183167a810518f2aa9f39?iv=af3abe9304c706f681857b64fc4e6127", + }, + { + name: "Joe", + birthday: "11/13/2104", + bookLink: "/link/link2", + }, + { + name: "Joslyn", + birthday: "11/13/2004", + bookLink: "/link/link3", + }, + ], + }, + }; +}; diff --git a/web/tailwind.config.js b/web/tailwind.config.js index 511cb78a..3d69b245 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -14,6 +14,8 @@ module.exports = { backgroundImage: { "custom-background": "radial-gradient(115.79% 108.31% at 24.4% 30.17%, #EDB1CB 0.01%, #B14378 92.53%)", + "admin-baby-book-background": + "radial-gradient(114.39% 277.05% at 79.56% 231.48%, #EDB1CB 0%, #B14378 100%)", }, fontFamily: { sans: ["Open Sans", ...defaultTheme.fontFamily.sans], From 75415b005f4a0cd4b072f50fcc4c5c182dc25de7 Mon Sep 17 00:00:00 2001 From: tsar-boomba Date: Sat, 28 Sep 2024 20:43:33 -0400 Subject: [PATCH 2/8] update admin album page --- web/components/BabyBook/PictureArray.tsx | 72 ++++++++++++++++++++++-- web/components/BabyBook/PictureModal.tsx | 16 +++--- web/components/BabyBook/Topbar.tsx | 19 +++---- web/components/Icons/DownloadIcon.tsx | 3 +- web/components/Icons/LinkIcon.tsx | 3 +- web/components/atoms/Button.tsx | 39 +++++++------ web/lib/hooks/useMap.ts | 49 ++++++++++++++++ web/pages/admin/book/[babyId].tsx | 56 +++++++++++++++++- 8 files changed, 209 insertions(+), 48 deletions(-) create mode 100644 web/lib/hooks/useMap.ts diff --git a/web/components/BabyBook/PictureArray.tsx b/web/components/BabyBook/PictureArray.tsx index 6dbecb37..be5241c5 100644 --- a/web/components/BabyBook/PictureArray.tsx +++ b/web/components/BabyBook/PictureArray.tsx @@ -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(null); const [showToTop, setShowToTop] = useState(false); @@ -71,16 +75,60 @@ const PictureArray = ({ babyBook, select }: Props) => {

{year.year}

{year.months.map((month, j) => { + const monthSelected = month.images.every((_, k) => + selectedForDownload.has(selectedForDownloadKey(i, j, k)) + ); + return (
-

- {monthIndexToString(month.month)} {year.year} +

{ + selectedForDownload.batch((map) => { + month.images.forEach((img, k) => { + const key = selectedForDownloadKey(i, j, k); + if (monthSelected) { + map.delete(key); + } else { + map.set(key, img); + } + }); + }); + }} + > + + + {monthIndexToString(month.month)} {year.year} +

{month.images.map((image, k) => ( select(i, j, k)} + selected={selectedForDownload.has( + selectedForDownloadKey(i, j, k) + )} + onCheckboxClick={() => { + if ( + selectedForDownload.has( + selectedForDownloadKey(i, j, k) + ) + ) { + selectedForDownload.delete( + selectedForDownloadKey(i, j, k) + ); + } else { + selectedForDownload.set( + selectedForDownloadKey(i, j, k), + image + ); + } + }} key={k} /> ))} @@ -106,13 +154,19 @@ 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 (
@@ -121,6 +175,15 @@ const BabyBookImage = ({ {image.caption}

)} + { + e.stopPropagation(); + onCheckboxClick(); + }} + />
); }; @@ -128,6 +191,7 @@ const BabyBookImage = ({ interface Props { babyBook: BabyBookYear[]; select: (arg0: number, arg1: number, arg2: number) => void; + selectedForDownload: UseMapWrapper; } export default PictureArray; diff --git a/web/components/BabyBook/PictureModal.tsx b/web/components/BabyBook/PictureModal.tsx index 53b5a5cb..3331b0b2 100644 --- a/web/components/BabyBook/PictureModal.tsx +++ b/web/components/BabyBook/PictureModal.tsx @@ -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"; @@ -37,13 +38,13 @@ const PictureModal = ({ ).toDate(); return (
-
+
deselect()} > -

Download

+

Back

@@ -90,13 +91,12 @@ const PictureModal = ({

{image.caption === "" ? "No Caption" : image.caption}

- + text="Download" + icon={} + width="auto" + />
diff --git a/web/components/BabyBook/Topbar.tsx b/web/components/BabyBook/Topbar.tsx index 4e426f0e..d113a91f 100644 --- a/web/components/BabyBook/Topbar.tsx +++ b/web/components/BabyBook/Topbar.tsx @@ -2,22 +2,15 @@ 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"; const TopBar = ({ number, motherName, name, content, iv }: 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); @@ -63,13 +56,19 @@ const TopBar = ({ number, motherName, name, content, iv }: Props) => {

Mother - {motherName}

-
+
); diff --git a/web/components/Icons/DownloadIcon.tsx b/web/components/Icons/DownloadIcon.tsx index 8c607246..291b3bc7 100644 --- a/web/components/Icons/DownloadIcon.tsx +++ b/web/components/Icons/DownloadIcon.tsx @@ -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" > ); diff --git a/web/components/Icons/LinkIcon.tsx b/web/components/Icons/LinkIcon.tsx index 25c6dbef..5c5099a0 100644 --- a/web/components/Icons/LinkIcon.tsx +++ b/web/components/Icons/LinkIcon.tsx @@ -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" > ); diff --git a/web/components/atoms/Button.tsx b/web/components/atoms/Button.tsx index 56d29649..0beb1cbf 100644 --- a/web/components/atoms/Button.tsx +++ b/web/components/atoms/Button.tsx @@ -31,25 +31,24 @@ export default function Button({ } return ( -
- -
+ ); } diff --git a/web/lib/hooks/useMap.ts b/web/lib/hooks/useMap.ts new file mode 100644 index 00000000..2590b51c --- /dev/null +++ b/web/lib/hooks/useMap.ts @@ -0,0 +1,49 @@ +import { Dispatch, SetStateAction, useRef, useState } from "react"; + +export type UseMapWrapper = { + set: (key: K, value: V) => void; + get: (key: K) => V | undefined; + delete: (key: K) => void; + has: (key: K) => boolean; + batch: (op: (map: Map) => void) => void; + clear: () => void; + entries: () => IterableIterator<[K, V]>; + size: number; +}; + +export const useMap = () => { + const mapRef = useRef(new Map()); + + const [wrapper, setWrapper] = useState>(createWrapper()); + + function createWrapper(): UseMapWrapper { + return { + set: (key, value) => { + mapRef.current.set(key, value); + setWrapper(createWrapper()); + }, + delete: (key) => { + if (mapRef.current.has(key)) { + setWrapper(createWrapper()); + } + mapRef.current.delete(key); + }, + get: (key) => mapRef.current.get(key), + has: (key) => mapRef.current.has(key), + entries: () => mapRef.current.entries(), + batch: (op) => { + op(mapRef.current); + setWrapper(createWrapper()); + }, + clear: () => { + if (mapRef.current.size > 0) setWrapper(createWrapper()); + mapRef.current = new Map(); + }, + get size() { + return mapRef.current.size; + }, + }; + } + + return wrapper; +}; diff --git a/web/pages/admin/book/[babyId].tsx b/web/pages/admin/book/[babyId].tsx index eae5fec7..9f4b1f88 100644 --- a/web/pages/admin/book/[babyId].tsx +++ b/web/pages/admin/book/[babyId].tsx @@ -17,6 +17,9 @@ import { GetServerSideProps } from "next"; import { Baby } from "@lib/types/baby"; import { useState } from "react"; import { decrypt } from "@lib/utils/encryption"; +import { useMap } from "@lib/hooks/useMap"; +import Button from "@components/atoms/Button"; +import DownloadIcon from "@components/Icons/DownloadIcon"; export default function BabyBook({ babyBook, @@ -28,11 +31,15 @@ export default function BabyBook({ const [isPictureSelected, setIsPictureSelected] = useState(false); const [selectedImage, setSelectedImage] = useState(); const [currIndexes, setCurrIndexes] = useState({ i: -1, j: -1, k: -1 }); + const selectedForDownload = useMap(); + const selectImage = (i: number, j: number, k: number) => { setIsPictureSelected(true); setSelectedImage(babyBook[i].months[j].images[k]); setCurrIndexes({ i, j, k }); + selectedForDownload.clear(); }; + const selectImageOffset = ( i: number, j: number, @@ -67,8 +74,13 @@ export default function BabyBook({ setIsPictureSelected(false); }; + console.log( + selectedForDownload.size, + Array.from(selectedForDownload.entries()) + ); + return ( -
+
- + {isPictureSelected && ( )} + {selectedForDownload.size > 0 && ( +
+
+ { + selectedForDownload.clear(); + }} + > + + +

+ {selectedForDownload.size} file + {selectedForDownload.size > 1 ? "s" : ""} selected +

+
+
+ )}
); From eab49e3f8c7f02c470abb7f3680467440b169011 Mon Sep 17 00:00:00 2001 From: tsar-boomba Date: Sat, 28 Sep 2024 20:50:02 -0400 Subject: [PATCH 3/8] minor design fixes on admin book page --- web/components/BabyBook/PictureModal.tsx | 2 +- web/components/BabyBook/Topbar.tsx | 40 +++++++++++++++--------- web/pages/admin/book/[babyId].tsx | 1 + 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/web/components/BabyBook/PictureModal.tsx b/web/components/BabyBook/PictureModal.tsx index 3331b0b2..942e42e5 100644 --- a/web/components/BabyBook/PictureModal.tsx +++ b/web/components/BabyBook/PictureModal.tsx @@ -44,7 +44,7 @@ const PictureModal = ({ onClick={() => deselect()} > -

Back

+

Back to album

diff --git a/web/components/BabyBook/Topbar.tsx b/web/components/BabyBook/Topbar.tsx index d113a91f..74ca74e8 100644 --- a/web/components/BabyBook/Topbar.tsx +++ b/web/components/BabyBook/Topbar.tsx @@ -5,7 +5,14 @@ import PersonIcon from "@components/Icons/PersonIcon"; import { useState } from "react"; import Button from "@components/atoms/Button"; -const TopBar = ({ number, motherName, name, content, iv }: Props) => { +const TopBar = ({ + number, + motherName, + name, + content, + iv, + isPictureSelected, +}: Props) => { const [copiedConfirmation, setCopiedConfirmation] = useState(false); const downloadAlbum = () => { @@ -56,20 +63,22 @@ const TopBar = ({ number, motherName, name, content, iv }: Props) => {

Mother - {motherName}

-
-
+ {!isPictureSelected && ( +
+
+ )}
); }; @@ -80,6 +89,7 @@ interface Props { name: string; content: string; iv: string; + isPictureSelected: boolean; } export default TopBar; diff --git a/web/pages/admin/book/[babyId].tsx b/web/pages/admin/book/[babyId].tsx index 9f4b1f88..dcea9a48 100644 --- a/web/pages/admin/book/[babyId].tsx +++ b/web/pages/admin/book/[babyId].tsx @@ -87,6 +87,7 @@ export default function BabyBook({ motherName={baby.mother} content={content} iv={iv} + isPictureSelected={isPictureSelected} />
From ee63dba1eeeba66eab63329b6ae7c999dd77e506 Mon Sep 17 00:00:00 2001 From: tsar-boomba Date: Sat, 28 Sep 2024 20:55:34 -0400 Subject: [PATCH 4/8] small little refactor for readability-n --- web/components/BabyBook/PictureArray.tsx | 52 ++++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/web/components/BabyBook/PictureArray.tsx b/web/components/BabyBook/PictureArray.tsx index be5241c5..6a58671d 100644 --- a/web/components/BabyBook/PictureArray.tsx +++ b/web/components/BabyBook/PictureArray.tsx @@ -106,32 +106,32 @@ const PictureArray = ({ babyBook, select, selectedForDownload }: Props) => {
- {month.images.map((image, k) => ( - select(i, j, k)} - selected={selectedForDownload.has( - selectedForDownloadKey(i, j, k) - )} - onCheckboxClick={() => { - if ( - selectedForDownload.has( - selectedForDownloadKey(i, j, k) - ) - ) { - selectedForDownload.delete( - selectedForDownloadKey(i, j, k) - ); - } else { - selectedForDownload.set( - selectedForDownloadKey(i, j, k), - image - ); - } - }} - key={k} - /> - ))} + {month.images.map((image, k) => { + const imageSelected = selectedForDownload.has( + selectedForDownloadKey(i, j, k) + ); + + return ( + 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} + /> + ); + })}
); From 910814cd2a373c0543871f35ecc08cb0e42ca3fe Mon Sep 17 00:00:00 2001 From: tsar-boomba Date: Mon, 30 Sep 2024 22:15:09 -0400 Subject: [PATCH 5/8] Clean up code for boss --- web/components/BabyBook/Topbar.tsx | 22 ++++++++-------------- web/components/Icons/XIcon.tsx | 26 ++++++++++++++++++++++++++ web/pages/admin/book/[babyId].tsx | 25 ++++--------------------- web/pages/caregiver/book/[babyId].tsx | 10 +++------- web/pages/caregiver/book/index.tsx | 10 +++++----- 5 files changed, 46 insertions(+), 47 deletions(-) create mode 100644 web/components/Icons/XIcon.tsx diff --git a/web/components/BabyBook/Topbar.tsx b/web/components/BabyBook/Topbar.tsx index 74ca74e8..efc381f0 100644 --- a/web/components/BabyBook/Topbar.tsx +++ b/web/components/BabyBook/Topbar.tsx @@ -4,6 +4,7 @@ import LinkIcon from "@components/Icons/LinkIcon"; import PersonIcon from "@components/Icons/PersonIcon"; import { useState } from "react"; import Button from "@components/atoms/Button"; +import Image from "next/image"; const TopBar = ({ number, @@ -37,19 +38,12 @@ const TopBar = ({
- - - + Motherhood Beyond Bars Logo

{name}'s album @@ -64,7 +58,7 @@ const TopBar = ({

{!isPictureSelected && ( -
+