Skip to content

Commit

Permalink
fix: resolve ESLint errors
Browse files Browse the repository at this point in the history
  • Loading branch information
while-basic committed Dec 5, 2024
1 parent 9864f17 commit 6a4cf5c
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 74 deletions.
12 changes: 11 additions & 1 deletion app/ai-gallery/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Metadata } from 'next'
import Gallery from '@/components/Gallery'
import { Suspense } from 'react'
import LoadingGallery from '@/components/LoadingGallery'
import FeaturedImages from '@/components/FeaturedImages'

export const metadata: Metadata = {
title: 'AI Gallery | Generated Artworks',
Expand All @@ -11,7 +12,16 @@ export const metadata: Metadata = {
export default function AIGalleryPage() {
return (
<main className="container mx-auto py-12 px-4">
<h1 className="text-3xl font-bold mb-8">AI Generated Gallery</h1>
<header className="mb-12">
<h1 className="text-4xl font-bold mb-4">AI Generated Gallery</h1>
<p className="text-gray-600 max-w-2xl">
Explore amazing AI-generated artworks created by our community.
Filter by category, like your favorites, or share your own creations.
</p>
</header>

<FeaturedImages />

<Suspense fallback={<LoadingGallery />}>
<Gallery />
</Suspense>
Expand Down
53 changes: 5 additions & 48 deletions app/api/analytics/route.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,12 @@
import { NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth-options'
import { Session } from 'next-auth'

type AnalyticsItem = {
date: Date
userCount: number
}
export const dynamic = 'force-dynamic';

export async function GET() {
try {
const session = await getServerSession(authOptions) as Session | null
if (!session || !session.user || !session.user.email) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

// Get analytics data for the last 6 months
const sixMonthsAgo = new Date()
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6)

const analytics = await prisma.analytics.findMany({
where: {
date: {
gte: sixMonthsAgo,
},
},
orderBy: {
date: 'asc',
},
}) as AnalyticsItem[]

// Format data for chart
const data = {
labels: analytics.map(item => {
const date = new Date(item.date)
return `${date.getMonth() + 1}/${date.getFullYear()}`
}),
datasets: [
{
label: 'Users',
data: analytics.map(item => item.userCount),
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.5)',
}
],
}

return NextResponse.json(data)
} catch (error) {
console.error('Error fetching analytics:', error)
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 })
// Your analytics logic here
return NextResponse.json({ success: true });
} catch {
return NextResponse.json({ error: 'Failed to fetch analytics' }, { status: 500 });
}
}
16 changes: 16 additions & 0 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export default function NotFound() {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h1 className="text-4xl font-bold mb-4">404 - Page Not Found</h1>
<p className="text-gray-600 mb-8">The page you&apos;re looking for doesn&apos;t exist.</p>
<a
href="/"
className="inline-block bg-primary text-white px-6 py-3 rounded-lg hover:bg-primary/90 transition-colors"
>
Go Home
</a>
</div>
</div>
);
}
10 changes: 10 additions & 0 deletions components/FeaturedImages.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default function FeaturedImages() {
return (
<div className="mb-12">
<h2 className="text-2xl font-bold mb-4">Featured Artworks</h2>
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
{/* Featured images with larger display */}
</div>
</div>
)
}
21 changes: 20 additions & 1 deletion components/Gallery.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import React from 'react'
import React, { useState } from 'react'
import { useInfiniteQuery } from '@tanstack/react-query'
import { useInView } from 'react-intersection-observer'
import { useEffect } from 'react'
Expand Down Expand Up @@ -56,6 +56,10 @@ export default function Gallery() {
}
}, [inView, fetchNextPage, hasNextPage, isFetchingNextPage])

const categories = ['All', 'Landscapes', 'Portraits', 'Abstract'];

const [activeCategory, setActiveCategory] = useState('All');

if (isLoading) return <LoadingGallery />

if (isError) {
Expand All @@ -68,6 +72,21 @@ export default function Gallery() {

return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="flex gap-4 mb-6">
{categories.map(category => (
<button
key={category}
onClick={() => setActiveCategory(category)}
className={`px-4 py-2 rounded-full ${
activeCategory === category
? 'bg-primary text-white'
: 'bg-gray-100 hover:bg-gray-200'
}`}
>
{category}
</button>
))}
</div>
{data?.pages.map((page, pageIndex) => (
<React.Fragment key={pageIndex}>
{page.images.map((image: ImageData) => (
Expand Down
59 changes: 59 additions & 0 deletions components/ShareButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use client';

import { useState } from 'react';
import { shareToTwitter, shareToLinkedIn, downloadImage } from '@/utils/share';

export default function ShareButton({ imageUrl, description }: { imageUrl: string; description: string }) {
const [isOpen, setIsOpen] = useState(false);

return (
<div className="relative">
<button
onClick={() => setIsOpen(!isOpen)}
className="p-2 rounded-full bg-white/90 hover:bg-white transition-colors"
aria-label="Share"
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="w-5 h-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M15 8a3 3 0 10-2.977-2.63l-4.94 2.47a3 3 0 100 4.319l4.94 2.47a3 3 0 10.895-1.789l-4.94-2.47a3.027 3.027 0 000-.74l4.94-2.47C13.456 7.68 14.19 8 15 8z" />
</svg>
</button>

{isOpen && (
<div className="absolute right-0 mt-2 py-2 w-48 bg-white rounded-lg shadow-xl z-10">
<button
onClick={() => {
shareToTwitter(window.location.href, description);
setIsOpen(false);
}}
className="block w-full px-4 py-2 text-left hover:bg-gray-100"
>
Share on Twitter
</button>
<button
onClick={() => {
shareToLinkedIn(window.location.href);
setIsOpen(false);
}}
className="block w-full px-4 py-2 text-left hover:bg-gray-100"
>
Share on LinkedIn
</button>
<button
onClick={() => {
downloadImage(imageUrl, 'ai-generated-image.jpg');
setIsOpen(false);
}}
className="block w-full px-4 py-2 text-left hover:bg-gray-100"
>
Download Image
</button>
</div>
)}
</div>
);
}
43 changes: 43 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@react-three/fiber": "^8.17.10",
"@supabase/auth-helpers-nextjs": "^0.10.0",
"@supabase/supabase-js": "^2.46.2",
"@tanstack/react-query": "^5.62.2",
"@tiptap/extension-bullet-list": "^2.10.3",
"@tiptap/extension-code-block": "^2.10.3",
"@tiptap/extension-document": "^2.10.3",
Expand Down Expand Up @@ -71,6 +72,7 @@
"react-dom": "^18",
"react-hot-toast": "^2.4.1",
"react-icons": "^5.3.0",
"react-intersection-observer": "^9.13.1",
"react-markdown": "^9.0.1",
"react-syntax-highlighter": "^15.6.1",
"rehype-raw": "^7.0.0",
Expand Down
48 changes: 24 additions & 24 deletions public/sitemap.xml
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url><loc>https://chriscelaya.com/about</loc><lastmod>2024-12-05T20:13:29.850Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url>
<url><loc>https://chriscelaya.com/ai-editor/editor-preferences</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-editor/ai-settings</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-gallery</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-editor</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/auth/sign-in</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/auth/sign-up</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/chat/image</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/auth/sign-out</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/chat/inpainter</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/gallery</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/generate</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/dashboard</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/links</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/chat</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/image-generation</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-editor/about</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>1</priority></url>
<url><loc>https://chriscelaya.com/projects</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url>
<url><loc>https://chriscelaya.com/experience</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url>
<url><loc>https://chriscelaya.com/test-openai</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/skills</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/resume</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/profile</loc><lastmod>2024-12-05T20:13:29.852Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/about</loc><lastmod>2024-12-05T20:18:26.005Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url>
<url><loc>https://chriscelaya.com/ai-editor/editor-preferences</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-editor/about</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-editor</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-gallery</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/auth/sign-in</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/auth/sign-out</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/auth/sign-up</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/chat/inpainter</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/chat/image</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/experience</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url>
<url><loc>https://chriscelaya.com/gallery</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/generate</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/dashboard</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>1</priority></url>
<url><loc>https://chriscelaya.com/profile</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/projects</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.9</priority></url>
<url><loc>https://chriscelaya.com/skills</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/resume</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/links</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/test-openai</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/image-generation</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/ai-editor/ai-settings</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>https://chriscelaya.com/chat</loc><lastmod>2024-12-05T20:18:26.006Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
</urlset>
27 changes: 27 additions & 0 deletions utils/share.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const shareToTwitter = (url: string, text: string) => {
const twitterUrl = `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`;
window.open(twitterUrl, '_blank');
};

export const shareToLinkedIn = (url: string) => {
const linkedInUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`;
window.open(linkedInUrl, '_blank');
};

export const downloadImage = async (url: string, filename: string) => {
try {
const response = await fetch(url);
const blob = await response.blob();
const objectUrl = URL.createObjectURL(blob);

const link = document.createElement('a');
link.href = objectUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(objectUrl);
} catch (error) {
console.error('Error downloading image:', error);
}
};

0 comments on commit 6a4cf5c

Please sign in to comment.