Skip to content

Commit

Permalink
Merge pull request #26 from OnlineArtGallery-SEP490-SP25-SE11/social-…
Browse files Browse the repository at this point in the history
…screen

Social screen
  • Loading branch information
bluefishhh93 authored Feb 12, 2025
2 parents be76c39 + e2d5cf6 commit bdd3ea6
Show file tree
Hide file tree
Showing 14 changed files with 691 additions and 135 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.3",
"@radix-ui/react-scroll-area": "^1.2.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Canvas } from "@react-three/fiber";
import { Environment, PerspectiveCamera, PointerLockControls, Preload } from "@react-three/drei";
import { ModernRoom } from "../../exhibitions/components/modern-room";
import { Suspense } from "react";
import { Suspense, useState, useCallback } from "react";
import { Physics } from "@react-three/cannon";
import Image from "next/image";
import { GalleryPreviewLoader } from "./gallery-preview-loader";
Expand All @@ -11,17 +11,28 @@ import { Crosshair } from "../../exhibitions/components/crosshair";
import Player from "../../exhibitions/components/player";

export function FeaturedGalleryPreview() {
const [isPointerLocked, setIsPointerLocked] = useState(false);

const handleCanvasClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
setIsPointerLocked(true);
}, []);

return (
<div className="relative w-full max-w-5xl mx-auto">
<div className="relative w-full max-w-5xl mx-auto"
onClick={handleCanvasClick}
>

<Image
src="/monitor-frame.png"
src="https://res.cloudinary.com/djvlldzih/image/upload/v1739338527/gallery/monitor-frame.png"
alt="Monitor Frame"
width={1920}
height={1080}
className="w-full h-auto relative z-20"
/>
<div className="absolute top-[5.5%] left-[3.5%] right-[3.5%] bottom-[20%] overflow-hidden">
<div
className="absolute top-[5.5%] left-[3.5%] right-[3.5%] bottom-[20%] overflow-hidden"
>
<Canvas
camera={{ position: [0, 2, 5], fov: 75 }}
gl={{ antialias: true }}
Expand Down Expand Up @@ -49,11 +60,15 @@ export function FeaturedGalleryPreview() {
</Physics>

<Preload all />
<PointerLockControls
maxPolarAngle={Math.PI * 0.7}
minPolarAngle={Math.PI * 0.3}
pointerSpeed={0.1}
/>
{isPointerLocked && (
<PointerLockControls
maxPolarAngle={Math.PI * 0.7}
minPolarAngle={Math.PI * 0.3}
pointerSpeed={0.1}
onLock={() => setIsPointerLocked(true)}
onUnlock={() => setIsPointerLocked(false)}
/>
)}
<Crosshair />
</Suspense>
</Canvas>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(public)/[locale]/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { FeaturedGalleryPreview } from './components/featured-gallery-preview';
export default function AboutPage() {
return (
<div className='min-h-screen flex flex-col font-[family-name:var(--font-geist-sans)]'>
<main className='flex-1 w-full mt-5'>
<main className='flex-1 w-full'>
<div className="relative w-full min-h-[90vh] flex items-center">
{/* Video Background */}
<video
Expand Down
3 changes: 2 additions & 1 deletion src/app/(public)/[locale]/artworks/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const mockArtPieces: ArtPiece[] = Array.from({ length: 1000 }, (_, i) => {
artist: ARTIST_NAMES[i % ARTIST_NAMES.length],
// imageUrl: `https://picsum.photos/id/${imageId}/${width}/${height}`,
imageUrl: `https://picsum.photos/seed/${i + 1}/${width}/${height}`,
price: Math.floor(Math.random() * 9000) + 1000, // 1000-10000
price: Math.floor(Math.random() * 950000) + 500000, // 500000-10000000
description: generateLoremIpsum(20),
width,
height
Expand Down Expand Up @@ -107,6 +107,7 @@ export async function fetchArtPiecesByRange(
stopIndex: number
): Promise<ArtPiece[]> {
// Giả sử rằng startIndex và stopIndex là các chỉ số trong mảng mockArtPieces
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const limit = stopIndex - startIndex + 1;
await new Promise((resolve) => setTimeout(resolve, 800)); // Slightly longer delay for realism

Expand Down
18 changes: 9 additions & 9 deletions src/app/(public)/[locale]/artworks/artworks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import ArtModal from '@/app/(public)/[locale]/artworks/components/art-modal';
import ArtFeed from '@/app/(public)/[locale]/artworks/components/art-feed';
import { ArtPiece } from '@/types/marketplace';
import { List, Masonry, useInfiniteLoader } from 'masonic';
import { useCallback, useMemo, useState } from 'react';
import FloatingSidebar from './components/art-sidebar';
import { useMemo, useState } from 'react';
// import FloatingSidebar from './components/art-sidebar';
import { AnimatePresence, motion } from 'framer-motion';

export default function Artworks({ artworks }: { artworks: ArtPiece[] }) {
const [artPieces, setArtPieces] = useState<ArtPiece[]>(artworks);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [masonryLayout, setMasonryLayout] = useState<boolean>(true);

const loadMore = useInfiniteLoader(
Expand Down Expand Up @@ -45,9 +46,9 @@ export default function Artworks({ artworks }: { artworks: ArtPiece[] }) {
}
};
}, []);
const changeLayout = useCallback(() => {
setMasonryLayout((prev) => !prev);
}, []);
// const changeLayout = useCallback(() => {
// setMasonryLayout((prev) => !prev);
// }, []);

const MasonryLayout =
// useCallback(
Expand All @@ -59,13 +60,12 @@ export default function Artworks({ artworks }: { artworks: ArtPiece[] }) {
exit='exit'
variants={animation.variants}
transition={animation.transition}
className='pl-10'
>
<Masonry
onRender={loadMore}
items={artPieces}
columnGutter={20}
columnWidth={280}
columnGutter={30}
columnWidth={380}
overscanBy={1.5}
render={ArtCard}
/>
Expand Down Expand Up @@ -102,7 +102,7 @@ export default function Artworks({ artworks }: { artworks: ArtPiece[] }) {
);
return (
<>
<FloatingSidebar changeLayout={changeLayout} />
{/* <FloatingSidebar changeLayout={changeLayout} /> */}
<div className='p-5'>
<AnimatePresence mode='wait'>
<motion.div layout>
Expand Down
61 changes: 20 additions & 41 deletions src/app/(public)/[locale]/artworks/components/art-card.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { ScrollArea } from '@/components/ui/scroll-area';
import { Skeleton } from '@/components/ui/skeleton';
import {
Tooltip,
TooltipContent,
TooltipTrigger
} from '@/components/ui/tooltip';
import { useArtModal } from '@/hooks/useArtModal';
import { ArtPiece } from '@/types/marketplace.d';
import { vietnamCurrency } from '@/utils/converters';
import { AnimatePresence, motion } from 'framer-motion';
import Image from 'next/image';
import React, { useCallback, useMemo, useState } from 'react';
Expand Down Expand Up @@ -38,7 +33,7 @@ const ArtCard: React.FC<ArtCardProps> = ({ data, width, index }) => {

return (
<motion.div
className='relative rounded-md overflow-hidden shadow-md'
className='relative overflow-hidden'
style={{
width,
height: scaledHeight // Set fixed height based on aspect ratio
Expand All @@ -64,52 +59,36 @@ const ArtCard: React.FC<ArtCardProps> = ({ data, width, index }) => {
</motion.div>
)}
</AnimatePresence>
<Tooltip>
<TooltipTrigger asChild>
<div className="flex flex-col w-full h-full">
<div className="relative w-full" style={{ height: `${scaledHeight - 60}px` }}>
<Image
src={data.imageUrl}
alt={data.title}
fill
sizes={`(max-width: 768px) 100vw, ${width}px`}
className={`object-cover ${hasError ? 'hidden' : ''}`}
priority={index < 4} // Load first 4 images immediately
priority={index < 4}
quality={85}
onLoad={handleImageLoad} // Hide skeleton when image loads
onError={handleImageError} // Handle errors
onLoad={handleImageLoad}
onError={handleImageError}
onClick={() => {
setSelected(data);
}}
/>
</TooltipTrigger>
<TooltipContent
align='center'
// className='max-w-xs p-4 space-y-2 acrylic rounded border backdrop-blur-lg text-black dark:text-white prose dark:prose-invert'
className='max-w-xs p-4 space-y-2 rounded border backdrop-blur-md bg-black/50 text-white prose dark:prose-invert'
sideOffset={5}
// style={
// {
// '--gradient-angle': '120deg',
// '--gradient-end': 'rgba(0, 0, 255, 0.2)'
// } as React.CSSProperties
// }
>
<h4 className='text-lg font-bold border-b border-gray-300 dark:border-gray-600 pb-2'>
{data.title}
</h4>
<ScrollArea className='h-48 w-full rounded-md p-3 shadow-inner prose-sm'>
<p>{data.description}</p>
</ScrollArea>
<div className='flex items-center justify-between text-sm'>
<p className='flex items-center gap-2'>
<span className='font-medium'>By:</span>
{data.artist}
</p>
<p className='text-base font-semibold text-green-600'>
${data.price}
</p>
</div>
<div className="p-2 bg-white dark:bg-gray-800">
<div className="flex items-center justify-between">
<div className="flex flex-col">
<span className="text-md font-medium truncate">
{data.title}
</span>
<span className="text-sm text-gray-500 dark:text-gray-400">
{vietnamCurrency(data.price)}
</span>
</div>
</div>
</TooltipContent>
</Tooltip>
</div>
</div>
</motion.div>
);
};
Expand Down
83 changes: 83 additions & 0 deletions src/app/(public)/[locale]/artworks/components/art-category.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"use client";

import Image from "next/image";
import Link from "next/link";

interface Category {
id: string;
name: string;
imageUrl: string;
slug: string;
}

const categories: Category[] = [
{
id: "1",
name: "Contemporary Art",
imageUrl: "https://images.unsplash.com/photo-1536924940846-227afb31e2a5?q=80&w=1470&h=800",
slug: "contemporary-art"
},
{
id: "2",
name: "Painting",
imageUrl: "https://images.unsplash.com/photo-1579783902614-a3fb3927b6a5?q=80&w=1470&h=800",
slug: "painting"
},
{
id: "3",
name: "Street Art",
imageUrl: "https://images.unsplash.com/photo-1561214115-f2f134cc4912?q=80&w=1470&h=800",
slug: "street-art"
},
{
id: "4",
name: "Photography",
imageUrl: "https://images.unsplash.com/photo-1554048612-b6a482bc67e5?q=80&w=1470&h=800",
slug: "photography"
},
{
id: "5",
name: "Emerging Art",
imageUrl: "https://images.unsplash.com/photo-1515405295579-ba7b45403062?q=80&w=1470&h=800",
slug: "emerging-art"
},
{
id: "6",
name: "20th-Century Art",
imageUrl: "https://images.unsplash.com/photo-1518998053901-5348d3961a04?q=80&w=1470&h=800",
slug: "20th-century-art"
}
];

const ArtCategory = () => {
return (
<div className="px-4 py-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-6">
{categories.map((category) => (
<Link
href={`/artworks/category/${category.slug}`}
key={category.id}
className="group"
>
<div className="flex flex-col space-y-3">
<div className="relative aspect-[16/9] overflow-hidden rounded-lg">
<Image
src={category.imageUrl}
alt={category.name}
fill
className="object-cover transition-transform duration-300 group-hover:scale-110"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
<span className="text-sm font-medium text-center block">
{category.name}
</span>
</div>
</Link>
))}
</div>
</div>
);
};

export default ArtCategory;
Loading

0 comments on commit bdd3ea6

Please sign in to comment.