Skip to content

Commit 466c7fd

Browse files
committed
fixing project
1 parent 8359535 commit 466c7fd

22 files changed

Lines changed: 2085 additions & 670 deletions

app/about.tsx

Lines changed: 62 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import * as api from '../lib/api';
55
import { Navbar } from '../components/Navbar';
66
import { Download, MapPin, Briefcase, GraduationCap, Mail, Github, Linkedin, Twitter, Instagram, Youtube, Code, Smartphone, Cloud, Terminal, Layout, Database, Zap } from 'lucide-react';
77
import { motion } from 'framer-motion';
8+
import ReactMarkdown from 'react-markdown';
9+
import { ensureFullUrl } from '../lib/utils';
810

911
const IconMap: { [key: string]: React.ElementType } = {
10-
code: Code,
11-
smartphone: Smartphone,
12-
cloud: Cloud,
13-
terminal: Terminal,
14-
layout: Layout,
15-
database: Database
12+
code: Code, smartphone: Smartphone, cloud: Cloud, terminal: Terminal, layout: Layout, database: Database
13+
};
14+
15+
const SocialIconMap: { [key: string]: React.ElementType } = {
16+
github: Github, linkedin: Linkedin, twitter: Twitter, instagram: Instagram, youtube: Youtube, mail: Mail,
1617
};
1718

1819
export default function AboutPage() {
@@ -26,80 +27,76 @@ export default function AboutPage() {
2627
const isLoading = isLoadingProfile || isLoadingExp || isLoadingEdu || isLoadingServices;
2728
const statsTheme = theme === 'dark' ? 'dark' : 'default';
2829

29-
// const getGithubUsername = (url: string | undefined) => {
30-
// if (!url) return '';
31-
// const cleanUrl = url.replace(/\/$/, ''); // Remove trailing slash
32-
// return cleanUrl.split('/').pop();
33-
// };
34-
// const username = getGithubUsername(profile?.socials.github);
30+
const getGithubUsername = (url: string | undefined) => {
31+
if (!url) return '';
32+
try {
33+
const urlObj = new URL(url);
34+
return urlObj.pathname.substring(1);
35+
} catch (e) {
36+
return '';
37+
}
38+
};
39+
40+
const username = getGithubUsername(ensureFullUrl((profile?.social_links as any)?.github));
3541

3642
if (isLoading) {
37-
return (
38-
<div className="min-h-screen bg-slate-50 dark:bg-slate-950 flex items-center justify-center">
39-
<p>Loading...</p>
40-
</div>
41-
)
43+
return <div className="min-h-screen bg-slate-50 dark:bg-slate-950 flex items-center justify-center"><p>Loading...</p></div>
4244
}
4345

4446
return (
4547
<div className="min-h-screen bg-slate-50 dark:bg-slate-950 text-slate-900 dark:text-white transition-colors duration-300">
4648
<Navbar />
4749
<div className="pt-32 pb-20 max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
4850

49-
{/* Header / Bio */}
5051
<div className="flex flex-col md:flex-row gap-12 items-start mb-20">
5152
<div className="w-full md:w-1/3 shrink-0">
5253
<div className="aspect-square rounded-2xl overflow-hidden border-4 border-white dark:border-slate-800 shadow-xl relative mb-6">
5354
<div className="absolute inset-0 bg-indigo-500/10 mix-blend-overlay" />
54-
<img src={profile?.avatar_url || ''} alt={profile?.full_name || 'User'} className="w-full h-full object-cover bg-white dark:bg-slate-900" />
55+
<img src={profile?.avatar_url || ''} alt={profile?.display_name || 'User'} className="w-full h-full object-cover bg-white dark:bg-slate-900" />
5556
</div>
5657

5758
<div className="flex flex-col gap-4">
58-
{/* Placeholder for Address & Socials */}
59+
{profile?.address && (
60+
<div className="flex items-center gap-3 text-slate-600 dark:text-slate-400"><MapPin className="h-5 w-5 text-indigo-500" /><span>{profile.address}</span></div>
61+
)}
62+
63+
<div className="flex flex-wrap gap-4 mt-2">
64+
{profile?.social_links && typeof profile.social_links === 'object' && Object.entries(profile.social_links).map(([key, value]) => {
65+
if (!value) return null;
66+
const Icon = SocialIconMap[key];
67+
if (!Icon) return null;
68+
const href = key === 'mail' ? `mailto:${value}` : ensureFullUrl(value as string) || '#';
69+
return (
70+
<a key={key} href={href} target="_blank" rel="noreferrer" className="p-2 bg-slate-200 dark:bg-slate-900 rounded-lg hover:bg-indigo-100 dark:hover:bg-indigo-900/50 text-slate-600 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors">
71+
<Icon className="h-5 w-5" />
72+
</a>
73+
)
74+
})}
75+
</div>
5976
</div>
6077

61-
<a
62-
href="#" // Placeholder for resume_url
63-
target="_blank"
64-
className="mt-8 w-full flex items-center justify-center gap-2 bg-indigo-600 hover:bg-indigo-700 text-white py-3 rounded-lg font-medium transition-all shadow-lg shadow-indigo-500/20"
65-
>
78+
<a href={ensureFullUrl(profile?.resume_url) || '#'} target="_blank" rel="noopener noreferrer" className="mt-8 w-full flex items-center justify-center gap-2 bg-indigo-600 hover:bg-indigo-700 text-white py-3 rounded-lg font-medium transition-all shadow-lg shadow-indigo-500/20">
6679
<Download className="h-5 w-5" /> Download CV
6780
</a>
6881
</div>
6982

7083
<div className="flex-1">
71-
<h1 className="text-4xl font-bold mb-6">About Me</h1>
84+
<h1 className="text-4xl font-bold mb-6">{profile?.display_name || 'About Me'}</h1>
7285
<div className="prose prose-lg prose-slate dark:prose-invert">
73-
<p className="whitespace-pre-wrap leading-relaxed text-slate-600 dark:text-slate-300">
74-
{/* Placeholder for detailed_bio */}
75-
</p>
86+
<ReactMarkdown>{profile?.detailed_bio || ''}</ReactMarkdown>
7687
</div>
7788
</div>
7889
</div>
7990

80-
{/* Services Section */}
8191
{services && services.length > 0 && (
8292
<div className="mb-20">
83-
<h2 className="text-2xl font-bold mb-8 flex items-center gap-3">
84-
<div className="p-2 bg-yellow-100 dark:bg-yellow-900/30 rounded-lg text-yellow-600 dark:text-yellow-400">
85-
<Zap className="h-6 w-6" />
86-
</div>
87-
What I Do
88-
</h2>
93+
<h2 className="text-2xl font-bold mb-8 flex items-center gap-3"><div className="p-2 bg-yellow-100 dark:bg-yellow-900/30 rounded-lg text-yellow-600 dark:text-yellow-400"><Zap className="h-6 w-6" /></div>What I Do</h2>
8994
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
9095
{services.map((service, idx) => {
9196
const Icon = service.icon_name ? IconMap[service.icon_name] || Code : Code;
9297
return (
93-
<motion.div
94-
key={service.id}
95-
initial={{ opacity: 0, y: 20 }}
96-
whileInView={{ opacity: 1, y: 0 }}
97-
transition={{ delay: idx * 0.1 }}
98-
className="bg-white border border-slate-200 dark:bg-slate-900/50 dark:border-white/5 p-6 rounded-xl hover:border-indigo-500/30 transition-all shadow-sm dark:shadow-none group"
99-
>
100-
<div className="h-12 w-12 bg-indigo-50 dark:bg-slate-800 rounded-lg flex items-center justify-center text-indigo-600 dark:text-indigo-400 mb-4 group-hover:bg-indigo-600 group-hover:text-white transition-colors">
101-
<Icon className="h-6 w-6" />
102-
</div>
98+
<motion.div key={service.id} initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} transition={{ delay: idx * 0.1 }} className="bg-white border border-slate-200 dark:bg-slate-900/50 dark:border-white/5 p-6 rounded-xl hover:border-indigo-500/30 transition-all shadow-sm dark:shadow-none group">
99+
<div className="h-12 w-12 bg-indigo-50 dark:bg-slate-800 rounded-lg flex items-center justify-center text-indigo-600 dark:text-indigo-400 mb-4 group-hover:bg-indigo-600 group-hover:text-white transition-colors"><Icon className="h-6 w-6" /></div>
103100
<h3 className="text-lg font-bold mb-2 text-slate-900 dark:text-white">{service.title}</h3>
104101
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed">{service.description}</p>
105102
</motion.div>
@@ -110,64 +107,47 @@ export default function AboutPage() {
110107
)}
111108

112109
<div className="grid md:grid-cols-2 gap-12 mb-20">
113-
{/* Experience */}
114110
<div>
115-
<h2 className="text-2xl font-bold mb-8 flex items-center gap-3">
116-
<div className="p-2 bg-indigo-100 dark:bg-indigo-900/30 rounded-lg text-indigo-600 dark:text-indigo-400">
117-
<Briefcase className="h-6 w-6" />
118-
</div>
119-
Experience
120-
</h2>
111+
<h2 className="text-2xl font-bold mb-8 flex items-center gap-3"><div className="p-2 bg-indigo-100 dark:bg-indigo-900/30 rounded-lg text-indigo-600 dark:text-indigo-400"><Briefcase className="h-6 w-6" /></div>Experience</h2>
121112
<div className="space-y-8 border-l-2 border-slate-200 dark:border-slate-800 ml-3 pl-8 relative">
122113
{experience?.map((exp, idx) => (
123-
<motion.div
124-
key={exp.id}
125-
initial={{ opacity: 0, x: -20 }}
126-
whileInView={{ opacity: 1, x: 0 }}
127-
transition={{ delay: idx * 0.1 }}
128-
className="relative"
129-
>
114+
<motion.div key={exp.id} initial={{ opacity: 0, x: -20 }} whileInView={{ opacity: 1, x: 0 }} transition={{ delay: idx * 0.1 }} className="relative">
130115
<span className="absolute -left-[41px] top-1 w-5 h-5 rounded-full border-4 border-white dark:border-slate-950 bg-indigo-500" />
131116
<h3 className="text-xl font-bold text-slate-900 dark:text-white">{exp.title}</h3>
132117
<div className="text-indigo-600 dark:text-indigo-400 font-medium mb-2">{exp.institution}</div>
133-
<div className="text-sm text-slate-500 mb-3">{exp.start_date} - {exp.end_date || 'Present'}</div>
134-
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed mb-3">
135-
{exp.description}
136-
</p>
118+
<div className="text-sm text-slate-500 mb-3">{exp.period}</div>
119+
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed mb-3">{exp.description}</p>
137120
</motion.div>
138121
))}
139122
</div>
140123
</div>
141124

142-
{/* Education */}
143125
<div>
144-
<h2 className="text-2xl font-bold mb-8 flex items-center gap-3">
145-
<div className="p-2 bg-purple-100 dark:bg-purple-900/30 rounded-lg text-purple-600 dark:text-purple-400">
146-
<GraduationCap className="h-6 w-6" />
147-
</div>
148-
Education
149-
</h2>
126+
<h2 className="text-2xl font-bold mb-8 flex items-center gap-3"><div className="p-2 bg-purple-100 dark:bg-purple-900/30 rounded-lg text-purple-600 dark:text-purple-400"><GraduationCap className="h-6 w-6" /></div>Education</h2>
150127
<div className="space-y-8 border-l-2 border-slate-200 dark:border-slate-800 ml-3 pl-8 relative">
151128
{education?.map((edu, idx) => (
152-
<motion.div
153-
key={edu.id}
154-
initial={{ opacity: 0, x: -20 }}
155-
whileInView={{ opacity: 1, x: 0 }}
156-
transition={{ delay: idx * 0.1 }}
157-
className="relative"
158-
>
129+
<motion.div key={edu.id} initial={{ opacity: 0, x: -20 }} whileInView={{ opacity: 1, x: 0 }} transition={{ delay: idx * 0.1 }} className="relative">
159130
<span className="absolute -left-[41px] top-1 w-5 h-5 rounded-full border-4 border-white dark:border-slate-950 bg-purple-500" />
160131
<h3 className="text-xl font-bold text-slate-900 dark:text-white">{edu.title}</h3>
161132
<div className="text-purple-600 dark:text-purple-400 font-medium mb-1">{edu.institution}</div>
162-
<div className="text-sm text-slate-500 mb-2">{edu.start_date} - {edu.end_date || 'Present'}</div>
163-
<p className="text-sm text-slate-600 dark:text-slate-400 mb-3">
164-
{edu.description}
165-
</p>
133+
<div className="text-sm text-slate-500 mb-2">{edu.period}</div>
134+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-3">{edu.description}</p>
166135
</motion.div>
167136
))}
168137
</div>
169138
</div>
170139
</div>
140+
141+
{username && (
142+
<div className="border-t border-slate-200 dark:border-white/10 pt-16">
143+
<h2 className="text-2xl font-bold mb-8 text-center text-slate-900 dark:text-white">Coding Activity</h2>
144+
<div className="flex flex-col md:flex-row gap-6 justify-center items-center">
145+
<img src={`https://github-readme-stats.vercel.app/api?username=${username}&show_icons=true&theme=${statsTheme}&bg_color=${statsTheme === 'dark' ? '0f172a' : 'ffffff'}&title_color=${statsTheme === 'dark' ? 'ffffff' : '0f172a'}&text_color=${statsTheme === 'dark' ? '94a3b8' : '475569'}&icon_color=6366f1&border_color=${statsTheme === 'dark' ? '1e293b' : 'e2e8f0'}`} alt="GitHub Stats" className="rounded-xl border border-slate-200 dark:border-white/10 shadow-lg max-w-full" />
146+
<img src={`https://github-readme-stats.vercel.app/api/top-langs/?username=${username}&layout=compact&theme=${statsTheme}&bg_color=${statsTheme === 'dark' ? '0f172a' : 'ffffff'}&title_color=${statsTheme === 'dark' ? 'ffffff' : '0f172a'}&text_color=${statsTheme === 'dark' ? '94a3b8' : '475569'}&border_color=${statsTheme === 'dark' ? '1e293b' : 'e2e8f0'}`} alt="Top Languages" className="rounded-xl border border-slate-200 dark:border-white/10 shadow-lg max-w-full" />
147+
</div>
148+
</div>
149+
)}
150+
171151
</div>
172152
</div>
173153
);

0 commit comments

Comments
 (0)