diff --git a/client/app/[username]/components/GallerySection.jsx b/client/app/[username]/components/GallerySection.jsx deleted file mode 100644 index f528b06..0000000 --- a/client/app/[username]/components/GallerySection.jsx +++ /dev/null @@ -1,36 +0,0 @@ -"use client"; -import styles from "./GallerySection.module.css"; - -export default function GallerySection({ posts, onPostClick }) { - return ( -
-
- {posts.length === 0 ? ( -

No posts yet.

- ) : ( - posts.map((post) => { - const firstImg = post.images[0]; - return ( -
onPostClick(post)} - style={{ cursor: "pointer" }} - > - {firstImg ? ( - {post.caption - ) : ( -
No Image
- )} -
- ); - }) - )} -
-
- ); -} diff --git a/client/app/[username]/components/GallerySection.module.css b/client/app/[username]/components/GallerySection.module.css deleted file mode 100644 index b197f77..0000000 --- a/client/app/[username]/components/GallerySection.module.css +++ /dev/null @@ -1,97 +0,0 @@ -/* Gallery Section */ -.gallerySection { - max-width: 1100px; - margin: 0 auto; -} - -.gridContainer { - display: grid; - grid-template-columns: repeat(3, 1fr); /* 3 per row */ - gap: 16px; -} -/* Thumbnail wrapper */ -.thumb { - position: relative; - width: 100%; - aspect-ratio: 1 / 1; /* square */ - overflow: hidden; - border-radius: 14px; - background: #e7e1d9; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08); - transition: transform 0.18s ease, box-shadow 0.18s ease; -} - -.thumb:hover { - transform: translateY(-4px); - box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12); -} - -.thumbImg { - width: 100%; - height: 100%; - object-fit: cover; - display: block; -} - -.thumbPlaceholder { - font-size: 0.8rem; - color: #8a8175; - font-family: system-ui, sans-serif; -} - -@media (max-width: 900px) { - .profileHeader { - flex-direction: column; - align-items: center; - text-align: center; - } - - .displayName { - font-size: 2rem; - } - - .bio { - max-width: 100%; - margin-left: auto; - margin-right: auto; - } - - .gridContainer { - grid-template-columns: repeat(2, 1fr); - } -} - -@media (max-width: 560px) { - .page { - padding: 1.5rem 1rem 3rem; - } - - .profileHeader { - padding: 1.5rem; - margin-bottom: 2rem; - border-radius: 1.5rem; - } - - .avatar, - .avatarPlaceholder { - width: 110px; - height: 110px; - font-size: 2.5rem; - } - - .displayName { - font-size: 1.5rem; - } - - .bio { - font-size: 0.9rem; - } - - .gridContainer { - grid-template-columns: 1fr; - gap: 12px; - } -} diff --git a/client/app/[username]/components/PostDetailModal.module.css b/client/app/[username]/components/PostDetailModal.module.css index 28b3a35..c030732 100644 --- a/client/app/[username]/components/PostDetailModal.module.css +++ b/client/app/[username]/components/PostDetailModal.module.css @@ -59,6 +59,7 @@ position: relative; } +/* Prompt: how can I customize the styling of the embla carousel component used within my media panel? I want to ensure that it can fit within the bounds of the post modal. Provide CSS examples to adjust its appearance, but do not modify the code, I will decide what to include */ .media :global(.carouselWrapper) { width: 100%; height: 100%; diff --git a/client/app/api/uploadthing/core.js b/client/app/api/uploadthing/core.js index e2fcab0..8f94eaf 100644 --- a/client/app/api/uploadthing/core.js +++ b/client/app/api/uploadthing/core.js @@ -32,7 +32,7 @@ export const ourFileRouter = { .onUploadComplete(async ({ metadata, file }) => { // This code RUNS ON YOUR SERVER after upload console.log("Upload complete for userId:", metadata.userId); - console.log("file url", file.url); + console.log("file url", file.ufsUrl); // Extract EXIF from uploaded image let exifData = null; @@ -42,7 +42,7 @@ export const ourFileRouter = { const response = await fetch(`${API_URL}/api/exif/extract`, { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ imageUrl: file.url }), + body: JSON.stringify({ imageUrl: file.ufsUrl }), }); if (response.ok) { diff --git a/client/app/feed/Feed.module.css b/client/app/feed/Feed.module.css index 4b44079..40b34c3 100644 --- a/client/app/feed/Feed.module.css +++ b/client/app/feed/Feed.module.css @@ -1,4 +1,11 @@ -/* Feed.module.css */ +/* Feed.module.css + * GenAI Usage Note: After implementing the feed's data fetching and component structure, + * I used Copilot for styling refinements. Example prompt: "Help style the feed container + * with appropriate spacing, a centered max-width layout, and a soft background." + * I maintained full control by reviewing each suggestion and ensuring consistency + * with our established color palette and spacing system. + */ + .page { min-height: 100vh; background-color: #f5f0eb; @@ -56,7 +63,11 @@ margin: 2rem 0; } -/* Category Filter Styles */ +/* Category Filter Styles: + * Prompt: Can you provide some potential approaches to styling a category filter bar + * for the feed page that complements the existing design? Do not implement any code, however, provide a number of suggestions + * and explain your reasoning for each one + */ .filterBar { display: flex; align-items: center; diff --git a/client/app/feed/components/Post.module.css b/client/app/feed/components/Post.module.css index 6b3ef6e..0c2b9d1 100644 --- a/client/app/feed/components/Post.module.css +++ b/client/app/feed/components/Post.module.css @@ -1,4 +1,10 @@ -/* Post.module.css */ +/* Post.module.css + * GenAI Usage Note: I designed the post component structure and functionality myself. + * For visual polish, I asked Copilot: "Style the post card with rounded corners, + * subtle shadow, and appropriate padding for a clean feed appearance." + * I reviewed the output and adjusted the coloring and shadow intensity to align with the rest of our design. + */ + .post { border-radius: 1.5rem; padding: 1.5rem; diff --git a/client/app/feed/components/likesDialog.module.css b/client/app/feed/components/likesDialog.module.css index 3f533da..05a765b 100644 --- a/client/app/feed/components/likesDialog.module.css +++ b/client/app/feed/components/likesDialog.module.css @@ -1,3 +1,13 @@ +/* likesDialog.module.css + * GenAI Usage Note: I built the likes dialog component and modal logic independently. + * For animation polish, I asked Copilot: "Add smooth fade-in and slide-up animations + * for the modal overlay and dialog box with appropriate timing." + * I did some research on what @keyframes does, and once I understood it, I came to the conclusion + * that it would be best to use it here. + * I reviewed the keyframe animations and adjusted duration values to ensure + * the transitions felt natural and weren't too slow. + */ + .overlay { position: fixed; top: 0; @@ -99,6 +109,7 @@ border-bottom: 1px solid #f0f0f0; } +/* prompt: How do I ensure the border doesn't apply to the last item only? */ .likeItem:last-child { border-bottom: none; } diff --git a/client/app/feed/components/postImage.module.css b/client/app/feed/components/postImage.module.css index 8e8f94e..44b4a7f 100644 --- a/client/app/feed/components/postImage.module.css +++ b/client/app/feed/components/postImage.module.css @@ -1,3 +1,11 @@ +/* postImage.module.css + * GenAI Usage Note: I implemented the image carousel logic using Embla Carousel library. + * For carousel button styling, I prompted Copilot: "Style navigation buttons with + * circular shape, semi-transparent background, and smooth hover transitions." + * I retained control by adjusting opacity, backdrop-filter, and z-index values + * to ensure buttons were visible but not obtrusive. + */ + .carouselWrapper { position: relative; width: 100%; @@ -16,6 +24,9 @@ justify-content: center; } +/* Prompt: Is it possible to use my own styling for the embla carousel component? + * If so, please give suggestions on how to approach that. +*/ .embla { overflow: hidden; border-radius: 1rem; diff --git a/client/app/upload/Upload.module.css b/client/app/upload/Upload.module.css index 7ec20a6..94c4097 100644 --- a/client/app/upload/Upload.module.css +++ b/client/app/upload/Upload.module.css @@ -1,3 +1,11 @@ +/* Upload.module.css + * GenAI Usage Note: After building the upload form structure and logic myself, + * I used Copilot to assist with visual styling elements. Specifically, I prompted: + * "Help style the upload page container with a soft background, centered layout, + * and proper spacing for a clean multi-step form appearance." + * I reviewed the suggestions and adjusted values to match our project's design system. + */ + .page { min-height: 100vh; background-color: #f5f0eb; diff --git a/client/app/upload/components/CategoriesStep.module.css b/client/app/upload/components/CategoriesStep.module.css index 4f6dd0e..c4bacfe 100644 --- a/client/app/upload/components/CategoriesStep.module.css +++ b/client/app/upload/components/CategoriesStep.module.css @@ -33,11 +33,6 @@ background-color: rgba(255, 255, 255, 0.8); } -.catDropdownBtn[aria-expanded="true"] { - border-color: #da8d72; - background-color: rgba(255, 255, 255, 0.9); -} - .catPlaceholder { color: #a49a87; } @@ -64,6 +59,9 @@ transition: transform 0.2s ease; } +/* Prompt: How can I rotate the caret icon when the dropdown is expanded? Give +* recommended approaches, would this be a CSS problem, or something I address in the JSX * file? +*/ .catDropdownBtn[aria-expanded="true"] .catCaret { transform: rotate(180deg); } diff --git a/client/app/upload/components/ReviewSubmitStep.jsx b/client/app/upload/components/ReviewSubmitStep.jsx index 937f53e..d1a9265 100644 --- a/client/app/upload/components/ReviewSubmitStep.jsx +++ b/client/app/upload/components/ReviewSubmitStep.jsx @@ -1,7 +1,6 @@ "use client"; -import useEmblaCarousel from "embla-carousel-react"; -import { useEffect, useState } from "react"; import styles from "./ReviewSubmitStep.module.css"; +import PostImage from "@/app/feed/components/postImage"; export default function ReviewSubmitStep({ uploadedFiles, @@ -12,28 +11,11 @@ export default function ReviewSubmitStep({ onSubmit, isSubmitting, }) { - const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }); - const [canScrollPrev, setCanScrollPrev] = useState(false); - const [canScrollNext, setCanScrollNext] = useState(false); - - useEffect(() => { - if (!emblaApi) return; - const onSelect = () => { - setCanScrollPrev(emblaApi.canScrollPrev()); - setCanScrollNext(emblaApi.canScrollNext()); - }; - emblaApi.on("select", onSelect); - emblaApi.on("reInit", onSelect); - onSelect(); - return () => { - emblaApi.off("select", onSelect); - emblaApi.off("reInit", onSelect); - }; - }, [emblaApi]); - - useEffect(() => { - if (emblaApi && uploadedFiles.length > 0) emblaApi.reInit(); - }, [emblaApi, uploadedFiles]); + // Convert uploadedFiles to image URLs for PostImage component + const imageUrls = uploadedFiles.map((file) => { + if (typeof file === "string") return file; + return file.url; + }); return ( <> @@ -41,39 +23,8 @@ export default function ReviewSubmitStep({

Photos ({uploadedFiles.length})

-
-
- {uploadedFiles.map((file, idx) => ( -
- {`preview -
- ))} -
-
- {uploadedFiles.length > 1 && ( -
- - - {uploadedFiles.length} images - - -
- )} + {/* use postImage instead of reimplementing image display */} +

Caption

diff --git a/client/app/upload/components/ReviewSubmitStep.module.css b/client/app/upload/components/ReviewSubmitStep.module.css index 55836e3..2f85747 100644 --- a/client/app/upload/components/ReviewSubmitStep.module.css +++ b/client/app/upload/components/ReviewSubmitStep.module.css @@ -23,65 +23,6 @@ color: #666; } -.embla { - overflow: hidden; - border-radius: 1rem; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); -} - -.emblaContainer { - display: flex; - gap: 0; -} - -.emblaSlide { - flex: 0 0 100%; - min-width: 0; -} - -.emblaSlide img { - width: 100%; - height: 400px; - object-fit: cover; - display: block; -} - -.carouselControls { - display: flex; - justify-content: center; - align-items: center; - gap: 1.5rem; - margin-top: 1rem; -} - -.carouselBtn { - background: #da8d72; - color: white; - border: none; - border-radius: 50%; - width: 40px; - height: 40px; - font-size: 1.2rem; - cursor: pointer; - transition: all 0.2s ease; -} - -.carouselBtn:hover:not(:disabled) { - background: #c97856; - transform: scale(1.1); -} - -.carouselBtn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.slideCounter { - font-size: 0.9rem; - color: #666; - font-weight: 500; -} - .stepButtons { display: flex; gap: 1rem; diff --git a/client/app/upload/components/StepIndicator.module.css b/client/app/upload/components/StepIndicator.module.css index 3200c26..143abc0 100644 --- a/client/app/upload/components/StepIndicator.module.css +++ b/client/app/upload/components/StepIndicator.module.css @@ -1,3 +1,10 @@ +/* StepIndicator.module.css + * GenAI Usage Note: I built the step indicator component logic independently, + * then asked Copilot: "Would it be possible to have a step indicator with + * circular steps and connecting lines that highlight the current step? If so, what are the types of CSS styles I can use to achieve this?" + * I kept control over the final design by tweaking sizes and transition timing. + */ + .stepIndicator { display: flex; align-items: center; diff --git a/client/app/upload/components/UploadImagesStep.jsx b/client/app/upload/components/UploadImagesStep.jsx index de827cd..b49b958 100644 --- a/client/app/upload/components/UploadImagesStep.jsx +++ b/client/app/upload/components/UploadImagesStep.jsx @@ -1,6 +1,5 @@ "use client"; import { UploadDropzone } from "@/utils/uploadthing"; -import { useEffect, useState } from "react"; import styles from "./UploadImagesStep.module.css"; import PostImage from "@/app/feed/components/postImage"; @@ -24,7 +23,7 @@ export default function UploadImagesStep({ } // Capture both URL and EXIF data from upload response const filesWithExif = res.map((f) => ({ - url: f.url, + url: f.url || f.ufsUrl, // Fallback to ufsUrl if url doesn't exist exif: f.serverData?.exif || null, })); setUploadedFiles((prev) => [...prev, ...filesWithExif]); diff --git a/client/app/upload/components/UploadImagesStep.module.css b/client/app/upload/components/UploadImagesStep.module.css index bdf8abb..b0cdcdc 100644 --- a/client/app/upload/components/UploadImagesStep.module.css +++ b/client/app/upload/components/UploadImagesStep.module.css @@ -46,11 +46,6 @@ margin: 0; } -.dropzone.active { - border-color: #da8d72; - background-color: rgba(218, 141, 114, 0.2); -} - /* Hide the default UploadThing button and allowed content text */ .dropzone :global(button) { display: none !important; @@ -60,70 +55,6 @@ display: none !important; } -.carouselContainer { - margin: 2rem 0; - position: relative; -} - -.embla { - overflow: hidden; - border-radius: 1rem; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); -} - -.emblaContainer { - display: flex; - gap: 0; -} - -.emblaSlide { - flex: 0 0 100%; - min-width: 0; -} - -.emblaSlide img { - width: 100%; - height: 400px; - object-fit: cover; - display: block; -} - -.carouselControls { - display: flex; - justify-content: center; - align-items: center; - gap: 1.5rem; - margin-top: 1rem; -} - -.carouselBtn { - background: #da8d72; - color: white; - border: none; - border-radius: 50%; - width: 40px; - height: 40px; - font-size: 1.2rem; - cursor: pointer; - transition: all 0.2s ease; -} - -.carouselBtn:hover:not(:disabled) { - background: #c97856; - transform: scale(1.1); -} - -.carouselBtn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.slideCounter { - font-size: 0.9rem; - color: #666; - font-weight: 500; -} - .stepButtons { display: flex; gap: 1rem;