Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 27 additions & 31 deletions src/components/ProjectImage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -54,44 +54,40 @@ type ImageConfig = {
class: string;
};

// Image configuration lookup table
type ConfigKey = `${'valid' | 'placeholder'}-${'featured' | 'thumbnail'}`;

const IMAGE_CONFIGS: Record<ConfigKey, Omit<ImageConfig, 'src' | 'class'>> = {
'valid-featured': {
widths: [400, 800, 1200],
formats: ['avif', 'webp'],
},
'valid-thumbnail': {
width: 96,
height: 96,
},
'placeholder-featured': {
width: 800,
height: 450,
},
'placeholder-thumbnail': {
width: 96,
height: 96,
},
};

function getImageConfig(
hasImage: boolean,
imageVariant: 'featured' | 'thumbnail',
imageSource: ImageMetadata
): ImageConfig {
if (hasImage && imageVariant === 'featured') {
return {
src: imageSource,
widths: [400, 800, 1200],
formats: ['avif', 'webp'],
class: cn(baseImageClasses, hoverClasses),
};
}

if (hasImage && imageVariant === 'thumbnail') {
return {
src: imageSource,
width: 96,
height: 96,
class: cn(baseImageClasses, hoverClasses),
};
}

if (imageVariant === 'featured') {
return {
src: placeholderImage,
width: 800,
height: 450,
class: baseImageClasses,
};
}
const configKey: ConfigKey = `${hasImage ? 'valid' : 'placeholder'}-${imageVariant}`;
const baseConfig = IMAGE_CONFIGS[configKey];

// thumbnail placeholder
return {
src: placeholderImage,
width: 96,
height: 96,
class: baseImageClasses,
...baseConfig,
src: hasImage ? imageSource : placeholderImage,
class: hasImage ? cn(baseImageClasses, hoverClasses) : baseImageClasses,
};
}

Expand Down
8 changes: 3 additions & 5 deletions src/data/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,8 @@ export const PROFILE_DATA = {
"I'm passionate about mentoring the next generation of technologists and contributing to open-source projects and research that advance the field of artificial intelligence.",
},

socialProfiles: [
'https://github.com/cbenge509',
'https://www.linkedin.com/in/crisbenge/',
],
// Derived from SOCIAL_LINKS for single source of truth
socialProfiles: SOCIAL_LINKS.map(link => link.href),

education: [{name: 'Columbia University'}, {name: 'UC Berkeley'}],
} as const;
};
17 changes: 11 additions & 6 deletions src/scripts/featured-project-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
* Stops propagation on GitHub links to prevent card navigation.
*/

let initialized = false;
// Track if listener already attached
let listenerAttached = false;

function initFeaturedProjectCards(): void {
// Prevent multiple initializations
if (initialized) return;
initialized = true;
// Use event delegation for efficiency - safe to call multiple times
// as we only attach one delegated listener to document
if (listenerAttached) return;
listenerAttached = true;

// Use event delegation for efficiency
document.addEventListener('click', event => {
const target = event.target as HTMLElement;
const githubLink = target.closest('[data-github-link]');
Expand All @@ -20,9 +21,13 @@ function initFeaturedProjectCards(): void {
});
}

// Initialize on DOMContentLoaded
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initFeaturedProjectCards);
} else {
initFeaturedProjectCards();
}

// Re-initialize on page navigation (for Astro view transitions)
// Event delegation is already set up, no need to re-attach
document.addEventListener('astro:page-load', initFeaturedProjectCards);
3 changes: 3 additions & 0 deletions src/scripts/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,6 @@ if (document.readyState === 'loading') {
} else {
initNavigation();
}

// Re-initialize on page navigation (for Astro view transitions)
document.addEventListener('astro:page-load', () => initNavigation());
5 changes: 4 additions & 1 deletion src/scripts/publication-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ function initPublicationCards(): void {
});
}

// Initialize on DOMContentLoaded
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initPublicationCards);
} else {
initPublicationCards();
}

// Re-initialize on page navigation (for Astro view transitions)
document.addEventListener('astro:page-load', initPublicationCards);
5 changes: 5 additions & 0 deletions src/utils/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export const AWARD_CATEGORY_COLORS = {
/**
* Education honor badge colors.
* Blue color scheme for academic distinctions.
*
* NOTE: Kept as named constant (not inlined) for:
* - Consistency with other badge color exports
* - Semantic clarity in component usage
* - Single source of truth for design changes
*/
export const EDUCATION_HONOR_COLORS =
'bg-blue-100 text-blue-800 dark:bg-blue-900/50 dark:text-blue-200' as const;
Expand Down