Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2cfdc37
Merge pull request #17 from ArchAIve-Project/main
Prakhar896 Jul 14, 2025
8f7c6e8
Added escape key function to catalogueItemView, added public gallery …
JunHammy Jul 14, 2025
047a126
Added profileSection with profileCard, refactored Section code to use…
JunHammy Jul 14, 2025
6d14304
Added animations to arrowOverlay. Refined all sections usage of arrow…
JunHammy Jul 14, 2025
7ea4d30
Removed unused variables
JunHammy Jul 14, 2025
98dafbf
Added placeholder public profile page
JunHammy Jul 16, 2025
afd397f
Added image rendering from backend
JunHammy Jul 18, 2025
e200a9c
Implemented MMSection to use the books returned from getCatalogue
JunHammy Jul 22, 2025
169afa0
Fix bug in catalogue where Section component is shared among all books
JunHammy Jul 22, 2025
9ce682b
Added navigation to get started button on homepage
JunHammy Jul 22, 2025
8db453a
Fixed public gallery to display artefacts in their respective categories
JunHammy Jul 22, 2025
d5c3f64
Fixed for PR
JunHammy Jul 23, 2025
7ebe789
Fixed zindex bug
JunHammy Jul 23, 2025
9309f72
Removed debug console
JunHammy Jul 23, 2025
89c3931
Renamed placeholder image
JunHammy Jul 23, 2025
d6ec5d2
Conditionally rendered section only if there are artefacts in the sec…
JunHammy Jul 24, 2025
6040555
Fixed loading states
JunHammy Jul 24, 2025
1101725
Used placeholderImage by import instead
JunHammy Jul 25, 2025
ed41541
Added json response checking for data retrieval in catalogue and publ…
JunHammy Jul 25, 2025
09eed71
Added jsonresponse imports
JunHammy Jul 25, 2025
8efc90d
Removed console.logs, shifted async function out of useeffect
JunHammy Jul 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added src/assets/placeholderImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 42 additions & 31 deletions src/components/Catalogue/arrowOverlay.jsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,51 @@
import { Box, Icon } from "@chakra-ui/react";
import { FaChevronLeft, FaChevronRight } from "react-icons/fa";
import { motion, AnimatePresence } from "framer-motion";

const ArrowOverlay = ({ direction, isDisabled, onClick }) => {
const MotionBox = motion.create(Box);

const ArrowOverlay = ({ direction, isDisabled, onClick, isOverflowing }) => {
const isLeft = direction === "left";

return (
<Box
position="absolute"
top={0}
bottom={0}
left={isLeft ? 0 : "auto"}
right={isLeft ? "auto" : 0}
width="100px"
display="flex"
alignItems="center"
justifyContent={isLeft ? "flex-start" : "flex-end"}
zIndex={1}
px={3}
bgGradient={isLeft ? "to-r" : "to-l"}
gradientFrom="rgb(255, 255, 255)"
gradientTo="rgba(255, 255, 255, 0)"
cursor={isDisabled ? "not-allowed" : "pointer"}
pointerEvents={isDisabled ? "none" : "auto"}
opacity={isDisabled ? 0.3 : 1}
transition="opacity 0.3s ease, background 0.3s ease"
onClick={onClick}
>
<Icon
as={isLeft ? FaChevronLeft : FaChevronRight}
color="black"
boxSize={8}
mx={1}
transition="transform 0.2s ease"
_hover={!isDisabled ? { transform: "scale(1.2)" } : {}}
/>
</Box>
<AnimatePresence>
{isOverflowing && (
<MotionBox
key={direction}
initial={{ opacity: 0, x: isLeft ? -20 : 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: isLeft ? -20 : 20 }}
transition={{ duration: 0.3 }}
position="absolute"
top={0}
bottom={0}
left={isLeft ? 0 : "auto"}
right={isLeft ? "auto" : 0}
width="100px"
display="flex"
alignItems="center"
justifyContent={isLeft ? "flex-start" : "flex-end"}
zIndex={10}
px={6}
bgGradient={isLeft ? "to-r" : "to-l"}
gradientFrom="rgb(255, 255, 255)"
gradientTo="rgba(255, 255, 255, 0)"
cursor={isDisabled ? "not-allowed" : "pointer"}
pointerEvents={isDisabled ? "none" : "auto"}
opacity={isDisabled ? 0.3 : 1}
onClick={onClick}
>
<Icon
as={isLeft ? FaChevronLeft : FaChevronRight}
color="black"
boxSize={8}
mx={1}
transition="transform 0.2s ease"
_hover={!isDisabled ? { transform: "scale(1.2)" } : {}}
/>
</MotionBox>
)}
</AnimatePresence>
);
};

Expand Down
13 changes: 9 additions & 4 deletions src/components/Catalogue/cardComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { Card, Image, Text, Skeleton } from "@chakra-ui/react";
import { useState } from "react";

const CardComponent = ({ imageSrc, itemTitle, itemDescription, isSelected, expanded }) => {
const [isImageLoaded, setIsImageLoaded] = useState(false);

const isLoading = !isImageLoaded;

const CardComponent = ({ imageSrc, itemTitle, itemDescription, isLoading, setIsLoading, isSelected, expanded }) => {
return (
<Card.Root overflow="hidden" boxShadow={isSelected ? "lg" : "md"} transition="all 0.3s ease-in-out">
<Skeleton loading={isLoading} height="180px">
<Image
src={imageSrc}
alt={itemTitle}
loading="lazy"
onLoad={() => setIsLoading(false)}
height="180px"
loading={expanded ? "eager" : "lazy"}
onLoad={() => setIsImageLoaded(true)}
height="180px"
width="100%"
/>
</Skeleton>
Expand Down
27 changes: 6 additions & 21 deletions src/components/Catalogue/cardItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@ import CardComponent from "./cardComponent";

const MotionBox = motion.create(Box);

const images = [
"https://images.unsplash.com/photo-1555041469-a586c61ea9bc?auto=format&fit=crop&w=1770&q=80",
"https://images.unsplash.com/photo-1519389950473-47ba0277781c?auto=format&fit=crop&w=1770&q=80",
"https://images.unsplash.com/photo-1506744038136-46273834b3fb?auto=format&fit=crop&w=1770&q=80",
"https://images.unsplash.com/photo-1600585154340-be6161a56a0c?auto=format&fit=crop&w=1770&q=80",
];

const CardItem = ({ itemTitle, itemDescription, selectedTitle, index }) => {
const CardItem = ({ itemTitle, itemDescription, selectedTitle, imageSrc }) => {
const isMobile = useBreakpointValue({ base: true, md: false });

const [isHovered, setIsHovered] = useState(false);
Expand All @@ -28,12 +21,6 @@ const CardItem = ({ itemTitle, itemDescription, selectedTitle, index }) => {
setIsSelected(selectedTitle === itemTitle);
}, [selectedTitle, itemTitle]);

const imageSrc = images[index % images.length];

useEffect(() => {
setIsLoading(true);
}, [imageSrc]);

const updateHoverPosition = () => {
const rect = cardRef.current?.getBoundingClientRect();
if (rect) {
Expand Down Expand Up @@ -104,6 +91,7 @@ const CardItem = ({ itemTitle, itemDescription, selectedTitle, index }) => {

return (
<>
{/* Base Card Container */}
<Box
ref={cardRef}
onMouseEnter={handleMouseEnter}
Expand All @@ -116,13 +104,13 @@ const CardItem = ({ itemTitle, itemDescription, selectedTitle, index }) => {
bg={isSelected ? "gray.100" : "white"}
borderRadius="md"
boxShadow={isSelected ? "lg" : "md"}
zIndex={isHovered ? 30 : "auto"} // Conditional z-index
>
<CardComponent
imageSrc={imageSrc}
itemTitle={itemTitle}
itemDescription={itemDescription}
isLoading={isLoading}
setIsLoading={setIsLoading}
isSelected={isSelected}
expanded={false}
/>
Expand All @@ -141,22 +129,19 @@ const CardItem = ({ itemTitle, itemDescription, selectedTitle, index }) => {
position: "fixed",
top: hoverPos.top,
left: hoverPos.left + 15,
zIndex: 10,
zIndex: 30, // Always high z-index for expanded card
pointerEvents: "auto",
width: "280px",
}}
onMouseLeave={handleMouseLeave}
onMouseEnter={() => setIsHovered(true)}
borderRadius="md"
border={isSelected ? "1px solid" : "none"}
borderColor={isSelected ? "blue.600" : "transparent"}
boxShadow={isSelected ? "0 0 15px 2px rgba(66,153,225,0.6)" : "2xl"}
boxShadow="2xl"
>
<CardComponent
imageSrc={imageSrc}
itemTitle={itemTitle}
itemDescription={itemDescription}
isLoading={isLoading}
isSelected={isSelected}
expanded={true}
/>
Expand All @@ -168,4 +153,4 @@ const CardItem = ({ itemTitle, itemDescription, selectedTitle, index }) => {
);
};

export default CardItem;
export default CardItem;
3 changes: 2 additions & 1 deletion src/components/Catalogue/catalogueItemView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ const CatalogueItemView = ({ isOpen, onClose, title, items, setDialogTitle, imag
useEffect(() => {
const handleKeyDown = (e) => {
if (!isOpen || isNavigating) return;
if (e.key === "ArrowLeft" && currentIndex > 0) prevItem();
if (e.key === "Escape") {onClose()}
else if (e.key === "ArrowLeft" && currentIndex > 0) prevItem();
else if (e.key === "ArrowRight" && currentIndex < items.length - 1) nextItem();
};
window.addEventListener("keydown", handleKeyDown);
Expand Down
119 changes: 74 additions & 45 deletions src/components/Catalogue/mmSection.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import { Box, Table, Text, useBreakpointValue } from "@chakra-ui/react";
import { useRef, useState, useEffect } from "react";
import { useEffect, useState, useRef } from "react";
import { Box, Text, Flex, useBreakpointValue, Image } from "@chakra-ui/react";
import CardItem from "./cardItem.jsx";
import ArrowOverlay from "./arrowOverlay.jsx";
import placeholderImage from "../../assets/placeholderImage.png"

const MMSection = ({ onItemClick, selectedTitle }) => {
const MMSection = ({ books = [], onItemClick, selectedTitle }) => {
const isMobile = useBreakpointValue({ base: true, md: false });

const items = Array.from({ length: 15 }).map((_, idx) => ({
id: idx + 1,
title: `Meeting ${idx + 1}`,
description: `Description for meeting ${idx + 1}`,
}));

const scrollRef = useRef(null);
const [atStart, setAtStart] = useState(true);
const [atEnd, setAtEnd] = useState(false);
Expand All @@ -20,9 +14,12 @@ const MMSection = ({ onItemClick, selectedTitle }) => {
const node = scrollRef.current;
if (!node) return;
setAtStart(node.scrollLeft === 0);
setAtEnd(Math.ceil(node.scrollLeft + node.clientWidth) >= node.scrollWidth);
setAtEnd(
Math.ceil(node.scrollLeft + node.clientWidth) >= node.scrollWidth
);
};

// Scroll detection on mount
useEffect(() => {
const node = scrollRef.current;
if (!node) return;
Expand Down Expand Up @@ -51,48 +48,80 @@ const MMSection = ({ onItemClick, selectedTitle }) => {
};

return (
<Box mt={5} position="relative">
<Text paddingLeft={14} textStyle="xl" zIndex={20} position="relative">
<Box mt={5} position="relative" overflow="hidden">
<Text
paddingLeft={14}
textStyle="xl"
zIndex={20}
position="relative"
mb={4}
>
Meeting Minutes
</Text>

{!isMobile && (
<>
<ArrowOverlay direction="left" isDisabled={atStart} onClick={() => scroll("left")} />
<ArrowOverlay direction="right" isDisabled={atEnd} onClick={() => scroll("right")} />
<ArrowOverlay
direction="left"
isDisabled={atStart}
onClick={() => scroll("left")}
isOverflowing={!atStart}
/>
<ArrowOverlay
direction="right"
isDisabled={atEnd}
onClick={() => scroll("right")}
isOverflowing={!atEnd}
/>
</>
)}

<Table.ScrollArea pt={6} pb={6} scrollbar="hidden" ref={scrollRef}>
<Table.Root size="sm" unstyled="true">
<Table.Body>
<Table.Row>
<Table.Cell minW={isMobile ? 10 : 20} verticalAlign="top" />
{items.map((item, index) => (
<Table.Cell
key={item.id}
minW="315px"
verticalAlign="top"
>
<Box
onClick={() => handleClick(item.title)}
cursor="pointer"
borderRadius="md"
>
<CardItem
index={index}
itemTitle={item.title}
itemDescription={item.description}
selectedTitle={selectedTitle}
/>
</Box>
</Table.Cell>
))}
<Table.Cell minW={10} verticalAlign="top" />
</Table.Row>
</Table.Body>
</Table.Root>
</Table.ScrollArea>
<Flex
ref={scrollRef}
overflowX="auto"
overflowY="hidden"
px={14}
py={6}
gap={4}
scrollBehavior="smooth"
css={{
"&::-webkit-scrollbar": { display: "none" },
msOverflowStyle: "none",
scrollbarWidth: "none",
}}
>
{books.map((book) => {
const firstImage = book.artefacts?.[0]?.id;
const imageSrc = firstImage
? `${import.meta.env.VITE_BACKEND_URL}/cdn/artefacts/${firstImage}`
: placeholderImage;

return (
<Box
key={book.id}
minW="315px"
flex="0 0 auto"
cursor="pointer"
borderRadius="md"
onClick={() => handleClick(book.title)}
>
{/* Hidden Image for preloading */}
<Image
src={imageSrc}
style={{ display: "none" }}
alt=""
/>

<CardItem
itemTitle={book.title}
itemDescription={book.subtitle}
selectedTitle={selectedTitle}
imageSrc={imageSrc}
/>
</Box>
);
})}
</Flex>
</Box>
);
};
Expand Down
33 changes: 33 additions & 0 deletions src/components/Catalogue/profileCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Box, Image, Text } from "@chakra-ui/react";
import { useNavigate } from "react-router-dom";

function ProfileCard() {
const navigate = useNavigate();

const handleProfileCardClick = () => {
navigate("/publicProfile");
};

return (
<Box
pl={14}
pt={6}
pb={6}
textAlign="center"
w={200}
transition="transform 0.2s ease-in-out"
_hover={{ transform: "scale(1.05)", cursor: "pointer" }}
>
<Image
src="https://placehold.co/150"
borderRadius="full"
objectFit="cover"
onClick={handleProfileCardClick}
mb={4}
/>
<Text>Name</Text>
</Box>
);
}

export default ProfileCard;
Loading