Add avatar asset

This commit is contained in:
gpt-engineer-app[bot] 2026-03-07 21:30:47 +00:00
parent 7e4eb6bf69
commit c5a617f544
3 changed files with 165 additions and 5 deletions

View file

@ -0,0 +1,38 @@
import { useRef, useState, useCallback, ReactNode } from 'react';
import { cn } from '@/lib/utils';
interface GlassCardProps {
children: ReactNode;
className?: string;
interactive?: boolean;
}
export const GlassCard = ({ children, className, interactive = true }: GlassCardProps) => {
const cardRef = useRef<HTMLDivElement>(null);
const [glowPos, setGlowPos] = useState({ x: 0, y: 0 });
const [isHovered, setIsHovered] = useState(false);
const handleMouseMove = useCallback((e: React.MouseEvent) => {
if (!cardRef.current || !interactive) return;
const rect = cardRef.current.getBoundingClientRect();
setGlowPos({ x: e.clientX - rect.left, y: e.clientY - rect.top });
}, [interactive]);
return (
<div
ref={cardRef}
className={cn('glass-card glass-card-hover rounded-2xl relative', className)}
onMouseMove={handleMouseMove}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{interactive && isHovered && (
<div
className="mouse-glow"
style={{ left: glowPos.x, top: glowPos.y, opacity: 1 }}
/>
)}
<div className="relative z-10">{children}</div>
</div>
);
};

View file

@ -0,0 +1,22 @@
import { useState, useEffect, useCallback, RefObject } from 'react';
export function useMousePosition(containerRef?: RefObject<HTMLElement>) {
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleMouseMove = useCallback((e: MouseEvent) => {
if (containerRef?.current) {
const rect = containerRef.current.getBoundingClientRect();
setPosition({ x: e.clientX - rect.left, y: e.clientY - rect.top });
} else {
setPosition({ x: e.clientX, y: e.clientY });
}
}, [containerRef]);
useEffect(() => {
const target = containerRef?.current || window;
target.addEventListener('mousemove', handleMouseMove as EventListener);
return () => target.removeEventListener('mousemove', handleMouseMove as EventListener);
}, [handleMouseMove, containerRef]);
return position;
}

View file

@ -1,11 +1,111 @@
// Update this page (the content is just a fallback if you fail to update the page) import { useRef } from 'react';
import { GlassCard } from '@/components/GlassCard';
import { useMousePosition } from '@/hooks/useMousePosition';
import avatar from '@/assets/avatar.png';
import { Home, MessageCircle, Rss, GitBranch, Search, ExternalLink } from 'lucide-react';
const links = [
{ icon: Home, label: 'Home', href: 'https://damaj.tech/', desc: 'Main page' },
{ icon: MessageCircle, label: 'Who Am I?', href: 'https://damaj.tech/site/whoami', desc: 'About me' },
{ icon: Rss, label: 'Blog', href: 'https://damaj.tech/site/blog', desc: 'My writings' },
];
const services = [
{ icon: GitBranch, label: 'Git Server', href: 'https://git.damaj.tech/', desc: 'Self-hosted Forgejo' },
{ icon: Search, label: 'SearXNG', href: 'https://searxng.damaj.tech/', desc: 'Private search engine' },
];
const Index = () => { const Index = () => {
const containerRef = useRef<HTMLDivElement>(null);
const mouse = useMousePosition(containerRef);
return ( return (
<div className="flex min-h-screen items-center justify-center bg-background"> <div
<div className="text-center"> ref={containerRef}
<h1 className="mb-4 text-4xl font-bold">Welcome to Your Blank App</h1> className="min-h-screen bg-background relative overflow-hidden"
<p className="text-xl text-muted-foreground">Start building your amazing project here!</p> >
{/* Global mouse glow */}
<div
className="fixed pointer-events-none z-0"
style={{
left: mouse.x,
top: mouse.y,
width: 600,
height: 600,
transform: 'translate(-50%, -50%)',
background: 'radial-gradient(circle, hsl(25 95% 55% / 0.06) 0%, transparent 70%)',
}}
/>
<div className="relative z-10 max-w-2xl mx-auto px-4 py-12 md:py-20 flex flex-col gap-5">
{/* Avatar + Intro */}
<GlassCard className="p-6 md:p-8">
<div className="flex items-center gap-5">
<img
src={avatar}
alt="Mohamad's avatar"
className="w-20 h-20 md:w-24 md:h-24 rounded-full ring-2 ring-primary/30"
/>
<div>
<h1 className="text-2xl md:text-3xl font-heading font-bold text-foreground">
👋 Hey There!
</h1>
<p className="text-muted-foreground mt-1 font-body">
My name is <span className="text-gradient font-semibold">Mohamad</span>
</p>
<p className="text-muted-foreground text-sm">
Welcome to my space. Feel free to look around.
</p>
</div>
</div>
</GlassCard>
{/* Website Content */}
<div>
<h2 className="text-xs font-mono uppercase tracking-widest text-muted-foreground mb-3 px-1">
Website Content
</h2>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
{links.map((link) => (
<a key={link.label} href={link.href} target="_blank" rel="noopener noreferrer">
<GlassCard className="p-5 h-full link-arrow-parent cursor-pointer">
<div className="flex items-start justify-between">
<link.icon className="w-5 h-5 text-primary mb-3" />
<ExternalLink className="w-3.5 h-3.5 text-muted-foreground link-arrow" />
</div>
<p className="font-heading font-semibold text-foreground">{link.label}</p>
<p className="text-xs text-muted-foreground mt-1">{link.desc}</p>
</GlassCard>
</a>
))}
</div>
</div>
{/* Self-hosted Services */}
<div>
<h2 className="text-xs font-mono uppercase tracking-widest text-muted-foreground mb-3 px-1">
Self-hosted Services
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{services.map((svc) => (
<a key={svc.label} href={svc.href} target="_blank" rel="noopener noreferrer">
<GlassCard className="p-5 h-full link-arrow-parent cursor-pointer">
<div className="flex items-start justify-between">
<svc.icon className="w-5 h-5 text-primary mb-3" />
<ExternalLink className="w-3.5 h-3.5 text-muted-foreground link-arrow" />
</div>
<p className="font-heading font-semibold text-foreground">{svc.label}</p>
<p className="text-xs text-muted-foreground mt-1">{svc.desc}</p>
</GlassCard>
</a>
))}
</div>
</div>
{/* Footer */}
<p className="text-center text-xs text-muted-foreground font-mono mt-4">
damaj.tech
</p>
</div> </div>
</div> </div>
); );