Skip to content

Commit 0b2559d

Browse files
committed
Version 2.0.3
1 parent beb93f2 commit 0b2559d

17 files changed

Lines changed: 849 additions & 323 deletions

File tree

app/globals.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
--accent-foreground: oklch(0.98 0 0);
2222
--destructive: oklch(0.577 0.245 27.325);
2323
--destructive-foreground: oklch(0.98 0 0);
24+
--success: oklch(0.6 0.2 145);
25+
--success-foreground: oklch(0.98 0 0);
2426
--border: oklch(0.88 0 0);
2527
--input: oklch(0.88 0 0);
2628
--ring: oklch(0.6 0.22 255);
@@ -58,6 +60,8 @@
5860
--accent-foreground: oklch(1 0 0);
5961
--destructive: oklch(0.5 0.25 27);
6062
--destructive-foreground: oklch(1 0 0);
63+
--success: oklch(0.65 0.22 145);
64+
--success-foreground: oklch(1 0 0);
6165
--border: oklch(0.35 0 0);
6266
--input: oklch(0.35 0 0);
6367
--ring: oklch(0.6 0.22 255);
@@ -96,6 +100,8 @@
96100
--color-accent-foreground: var(--accent-foreground);
97101
--color-destructive: var(--destructive);
98102
--color-destructive-foreground: var(--destructive-foreground);
103+
--color-success: var(--success);
104+
--color-success-foreground: var(--success-foreground);
99105
--color-border: var(--border);
100106
--color-input: var(--input);
101107
--color-ring: var(--ring);

components/molecules/project-card.tsx

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Badge } from '@/components/ui/badge';
2+
import { DOMAIN_TECH_MAP } from '@/lib/constants';
23
import { Project } from '@/lib/projects';
34
import { cn } from '@/lib/utils';
45
import { Briefcase, ImageIcon } from 'lucide-react';
@@ -14,17 +15,21 @@ export function ProjectCard({ project, index }: ProjectCardProps) {
1415
const {
1516
id,
1617
title,
17-
description,
18+
fullDescription,
1819
images,
1920
domains,
2021
technologies,
2122
careerExperience,
2223
} = project;
2324
// Truncate description to ~150 characters
25+
const firstFullDescription =
26+
fullDescription && fullDescription.length > 0
27+
? fullDescription[0]
28+
: 'Mike is currently updating the description...';
2429
const truncatedDescription =
25-
description.length > 150
26-
? `${description.substring(0, 150)}...`
27-
: description;
30+
firstFullDescription.length > 80
31+
? `${firstFullDescription.substring(0, 80)}...`
32+
: firstFullDescription;
2833

2934
return (
3035
<Link
@@ -71,17 +76,28 @@ export function ProjectCard({ project, index }: ProjectCardProps) {
7176
)}
7277

7378
{/* Tags */}
74-
<div className="flex flex-wrap gap-2">
79+
<div className="flex flex-wrap gap-1">
7580
{domains.slice(0, 2).map((domain) => (
7681
<Badge key={domain} variant="secondary" className="text-xs">
7782
{domain}
7883
</Badge>
7984
))}
80-
{technologies.slice(0, 2).map((tech) => (
81-
<Badge key={tech} variant="outline" className="text-xs">
82-
{tech}
85+
{technologies.slice(0, 2).map((tech) => {
86+
const domain =
87+
DOMAIN_TECH_MAP.flatMap((domain) => domain.technologies).find(
88+
(t) => t.key === tech
89+
)?.name ?? tech;
90+
return (
91+
<Badge key={tech} variant="outline" className="text-xs">
92+
{domain}
93+
</Badge>
94+
);
95+
})}
96+
{domains.length + technologies.length > 4 && (
97+
<Badge key="more" variant="secondary" className="text-xs">
98+
{`+ ${domains.length + technologies.length - 4} more`}
8399
</Badge>
84-
))}
100+
)}
85101
</div>
86102
</div>
87103
</Link>

components/templates/projectDetails.tsx

Lines changed: 90 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { ImageCarousel } from '@/components/organisms/image-carousel';
22
import { TechStackDiagram } from '@/components/organisms/tech-stack-diagram';
3-
import { Badge } from '@/components/ui/badge';
43
import { Project } from '@/lib/projects';
54
import { ArrowLeft, Briefcase, ExternalLink, Github } from 'lucide-react';
65
import Link from 'next/link';
@@ -25,13 +24,13 @@ export default async function ProjectDetailsView({
2524
if (level === 1) {
2625
return (
2726
<h2 key={index} className="mt-8 text-2xl font-bold first:mt-0">
28-
{text}
27+
{renderInlineFormatting(text)}
2928
</h2>
3029
);
3130
} else {
3231
return (
3332
<h3 key={index} className="mt-6 text-xl font-semibold first:mt-0">
34-
{text}
33+
{renderInlineFormatting(text)}
3534
</h3>
3635
);
3736
}
@@ -45,7 +44,7 @@ export default async function ProjectDetailsView({
4544
key={index}
4645
className="mt-6 text-lg font-bold tracking-wide uppercase first:mt-0"
4746
>
48-
{text}
47+
{renderInlineFormatting(text)}
4948
</h3>
5049
);
5150
}
@@ -56,7 +55,7 @@ export default async function ProjectDetailsView({
5655
return (
5756
<li
5857
key={index}
59-
className="text-muted-foreground ml-6 text-base leading-relaxed"
58+
className="text-foreground/85 ml-6 text-base leading-relaxed"
6059
>
6160
{renderInlineFormatting(text)}
6261
</li>
@@ -65,37 +64,57 @@ export default async function ProjectDetailsView({
6564

6665
// Regular paragraph with inline formatting
6766
return (
68-
<p
69-
key={index}
70-
className="text-muted-foreground text-base leading-relaxed"
71-
>
67+
<p key={index} className="text-foreground/85 text-base leading-relaxed">
7268
{renderInlineFormatting(paragraph)}
7369
</p>
7470
);
7571
}
7672

77-
// Helper function to render inline formatting (bold, italic, etc.)
73+
// Helper function to render inline formatting (links and styled text)
7874
function renderInlineFormatting(text: string) {
79-
// Split by ** for bold text
80-
const parts = text.split(/(\*\*.*?\*\*)/g);
75+
// First, split by markdown links [text](url)
76+
const linkPattern = /(\[.*?\]\(.*?\))/g;
77+
const linkParts = text.split(linkPattern);
78+
79+
return linkParts.map((linkPart, linkIndex) => {
80+
// Check if this part is a markdown link
81+
const linkMatch = linkPart.match(/\[(.*?)\]\((.*?)\)/);
8182

82-
return parts.map((part, i) => {
83-
// Bold text wrapped in **
84-
if (part.startsWith('**') && part.endsWith('**')) {
85-
const content = part.slice(2, -2);
83+
if (linkMatch) {
84+
const [, linkText, url] = linkMatch;
8685
return (
87-
<strong key={i} className="text-foreground font-semibold">
88-
{content}
89-
</strong>
86+
<Link
87+
key={linkIndex}
88+
href={url}
89+
target="_blank"
90+
rel="noopener noreferrer"
91+
className="text-primary font-medium hover:underline"
92+
>
93+
{linkText}
94+
</Link>
9095
);
9196
}
9297

93-
// Check for HTML strong tags
94-
if (part.includes('<strong>') || part.includes('<em>')) {
95-
return <span key={i} dangerouslySetInnerHTML={{ __html: part }} />;
96-
}
97-
98-
return part;
98+
// Process remaining text for styled text {text|className}
99+
const stylePattern = /(\{.*?\|.*?\})/g;
100+
const styleParts = linkPart.split(stylePattern);
101+
102+
return styleParts.map((stylePart, styleIndex) => {
103+
// Check if this part is styled text
104+
const styleMatch = stylePart.match(/\{(.*?)\|(.*?)\}/);
105+
106+
if (styleMatch) {
107+
const [, styledText, className] = styleMatch;
108+
return (
109+
<span key={`${linkIndex}-${styleIndex}`} className={className}>
110+
{styledText}
111+
</span>
112+
);
113+
}
114+
115+
// Return plain text
116+
return stylePart;
117+
});
99118
});
100119
}
101120

@@ -108,7 +127,7 @@ export default async function ProjectDetailsView({
108127
className="text-muted-foreground hover:text-primary inline-flex items-center gap-2 transition-colors"
109128
>
110129
<ArrowLeft size={20} />
111-
<span>Back to Projects</span>
130+
<span>{'Back to Projects'}</span>
112131
</Link>
113132
<h1 className="text-4xl font-bold sm:text-5xl md:text-6xl">
114133
{project.title}
@@ -134,61 +153,71 @@ export default async function ProjectDetailsView({
134153
{/* Project Details */}
135154
<div className="animate-fade-in-delay-2 space-y-8">
136155
{/* Category Badges and Links */}
137-
<div className="flex flex-wrap items-center gap-3">
138-
{project.domains.map((domain) => (
156+
{project.githubUrl && project.liveUrl && (
157+
<div className="flex flex-wrap items-center gap-3">
158+
{/* {project.domains.map((domain) => (
139159
<Badge key={domain} variant="secondary" className="text-sm">
140160
{domain}
141161
</Badge>
162+
))} */}
163+
{project.githubUrl && (
164+
<a
165+
href={project.githubUrl}
166+
target="_blank"
167+
rel="noopener noreferrer"
168+
className="text-muted-foreground hover:text-primary p-2 transition-colors"
169+
aria-label="View on GitHub"
170+
>
171+
<Github size={20} />
172+
</a>
173+
)}
174+
{project.liveUrl && (
175+
<a
176+
href={project.liveUrl}
177+
target="_blank"
178+
rel="noopener noreferrer"
179+
className="text-muted-foreground hover:text-primary p-2 transition-colors"
180+
aria-label="View live site"
181+
>
182+
<ExternalLink size={20} />
183+
</a>
184+
)}
185+
</div>
186+
)}
187+
188+
{/* Achievements */}
189+
<div className="space-y-4">
190+
{project.achievements.map((paragraph, index) => (
191+
<p key={index} className="text-base leading-relaxed">
192+
{renderInlineFormatting(paragraph)}
193+
</p>
142194
))}
143-
{project.githubUrl && (
144-
<a
145-
href={project.githubUrl}
146-
target="_blank"
147-
rel="noopener noreferrer"
148-
className="text-muted-foreground hover:text-primary p-2 transition-colors"
149-
aria-label="View on GitHub"
150-
>
151-
<Github size={20} />
152-
</a>
153-
)}
154-
{project.liveUrl && (
155-
<a
156-
href={project.liveUrl}
157-
target="_blank"
158-
rel="noopener noreferrer"
159-
className="text-muted-foreground hover:text-primary p-2 transition-colors"
160-
aria-label="View live site"
161-
>
162-
<ExternalLink size={20} />
163-
</a>
164-
)}
165195
</div>
166196

167197
{/* Full Description */}
168198
<div className="space-y-4">
199+
<h2 className="mt-8 text-2xl font-bold first:mt-0">
200+
{'What is this project about?'}
201+
</h2>
169202
{project.fullDescription.map((paragraph, index) =>
170203
renderFormattedParagraph(paragraph, index)
171204
)}
172205
</div>
173206

207+
{/* Lessons Learned */}
208+
<div className="space-y-4">
209+
{project.lessons.map((paragraph, index) =>
210+
renderFormattedParagraph(paragraph, index)
211+
)}
212+
</div>
213+
174214
{/* Tech Stack */}
175215
<div className="space-y-1">
176216
<h2 className="flex items-center gap-2 text-xl font-bold">
177217
<span>🛠️</span>
178218
<span>Tech Stack</span>
179219
</h2>
180220
<TechStackDiagram technologies={project.technologies} />
181-
{/* Old Tech Stack Implementation - Commented Out */}
182-
{/* <div className="flex flex-wrap gap-3">
183-
{project.technologies.map((tech) => (
184-
<div
185-
key={tech}
186-
className="bg-card border-border hover:border-primary flex items-center gap-2 rounded-lg border px-4 py-2 transition-colors"
187-
>
188-
<span className="text-sm font-medium">{tech}</span>
189-
</div>
190-
))}
191-
</div> */}
192221
</div>
193222
</div>
194223
</div>

0 commit comments

Comments
 (0)