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
4 changes: 0 additions & 4 deletions .env.example

This file was deleted.

4 changes: 2 additions & 2 deletions app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export default defineAppConfig({
global: {
picture: {
dark: 'https://images.unsplash.com/photo-1701615004837-40d8573b6652?q=80&w=1480&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
light: 'https://images.unsplash.com/photo-1701615004837-40d8573b6652?q=80&w=1480&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
dark: 'https://i.ibb.co/JwbtXK8h/Imagen-de-Whats-App-2025-06-07-a-las-11-38-48-71b6a95e.jpg',
light: 'https://i.ibb.co/JwbtXK8h/Imagen-de-Whats-App-2025-06-07-a-las-11-38-48-71b6a95e.jpg',
alt: 'My profile picture'
},
meetingLink: 'https://cal.com/',
Expand Down
4 changes: 2 additions & 2 deletions app/components/landing/About.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import type { IndexCollectionItem } from '@nuxt/content'
import type { IndexCollectionItem, AboutCollectionItem } from '@nuxt/content'

defineProps<{
page: IndexCollectionItem
page: IndexCollectionItem | AboutCollectionItem
}>()
</script>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import type { IndexCollectionItem } from '@nuxt/content'
import type { IndexCollectionItem, AboutCollectionItem } from '@nuxt/content'

defineProps<{
page: IndexCollectionItem
page: IndexCollectionItem | AboutCollectionItem
}>()
</script>

Expand Down
119 changes: 119 additions & 0 deletions app/components/landing/Events.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<script setup lang="ts">
import type { AboutCollectionItem } from '@nuxt/content'
import { computed } from 'vue'

type Achievement = {
category: 'Programación' | 'Análisis de Datos' | 'Desarrollo Web'
title: string
date: Date | string
description: string
certificateUrl?: string
}

type ExtendedAboutCollection = AboutCollectionItem & {
achievements: Achievement[]
}

const props = defineProps<{
page: ExtendedAboutCollection
}>()

console.log('Page data:', props.page)

const groupedAchievements = computed(() => {
const achievements = props.page?.achievements || []
console.log('Achievements:', achievements)

const groups = {
'Programación': achievements.filter(a => a.category === 'Programación'),
'Análisis de Datos': achievements.filter(
a => a.category === 'Análisis de Datos'
),
'Desarrollo Web': achievements.filter(
a => a.category === 'Desarrollo Web'
)
}

console.log('Grouped:', groups)
return groups
})

const formatDate = (date: Date | string) => {
const dateObj = date instanceof Date ? date : new Date(date)
return dateObj.toLocaleDateString('es-ES', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
}
</script>

<template>
<UPageSection
title="Logros"
description="Tus ultimos logros"
:ui="{
container: '!p-0 gap-8 sm:gap-8',
title: 'text-left text-2xl sm:text-2xl lg:text-3xl font-medium',
description: 'mt-2 text-muted text-left'
}"
>
<div class="mt-8 space-y-16">
<div
v-for="(achievementsInCategory, category) in groupedAchievements"
v-show="achievementsInCategory.length > 0"
:key="category"
class="grid grid-cols-1 lg:grid-cols-3 lg:gap-8"
>
<div class="lg:col-span-1 mb-4 lg:mb-0">
<h2
class="lg:sticky lg:top-16 text-xl font-semibold tracking-tight text-highlighted"
>
{{ category }}
</h2>
</div>

<div class="lg:col-span-2 space-y-8">
<Motion
v-for="(achievement, index) in achievementsInCategory"
:key="index"
:initial="{ opacity: 0, transform: 'translateY(20px)' }"
:while-in-view="{ opacity: 1, transform: 'translateY(0)' }"
:transition="{ delay: 0.2 * index }"
:in-view-options="{ once: true }"
>
<div class="group relative pl-6 border-l border-default">
<div class="mb-1 text-sm font-medium text-muted">
{{ formatDate(achievement.date) }}
</div>

<h3 class="text-lg font-semibold text-highlighted">
{{ achievement.title }}
</h3>

<p class="mt-2 text-muted">
{{ achievement.description }}
</p>

<UButton
v-if="achievement.certificateUrl"
:to="achievement.certificateUrl"
target="_blank"
label="Ver certificado"
variant="link"
class="p-0 pt-2 gap-0"
>
<template #trailing>
<UIcon
name="i-lucide-arrow-right"
class="size-4 transition-all opacity-0 group-hover:translate-x-1 group-hover:opacity-100"
/>
</template>
</UButton>
</div>
</Motion>
</div>
</div>
</div>
</UPageSection>
</template>
95 changes: 75 additions & 20 deletions app/pages/about.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ useSeoMeta({
<template>
<UPage v-if="page">
<UPageHero
:title="page.title"
:description="page.description"
orientation="horizontal"
:ui="{
container: 'lg:flex sm:flex-row items-center',
Expand All @@ -33,30 +31,87 @@ useSeoMeta({
links: 'justify-start'
}"
>
<UColorModeAvatar
class="sm:rotate-4 size-36 rounded-lg ring ring-default ring-offset-3 ring-offset-(--ui-bg)"
:light="global.picture?.light!"
:dark="global.picture?.dark!"
:alt="global.picture?.alt!"
/>
<template #headline>
<Motion
:initial="{
scale: 1.1,
opacity: 0,
filter: 'blur(20px)'
}"
:animate="{
scale: 1,
opacity: 1,
filter: 'blur(0px)'
}"
:transition="{
duration: 0.6,
delay: 0.1
}"
>
<UColorModeAvatar
class="size-70 rounded-full ring ring-blue-100 ring-offset-3 ring-offset-(--ui-bg)"
:light="global.picture?.light!"
:dark="global.picture?.dark!"
:alt="global.picture?.alt!"
/>
</Motion>
</template>
<template #title>
<Motion
:initial="{
scale: 1.1,
opacity: 0,
filter: 'blur(20px)'
}"
:animate="{
scale: 1,
opacity: 1,
filter: 'blur(0px)'
}"
:transition="{
duration: 0.6,
delay: 0.1
}"
>
{{ page.title }}
</Motion>
</template>

<template #description>
<Motion
:initial="{
scale: 1.1,
opacity: 0,
filter: 'blur(20px)'
}"
:animate="{
scale: 1,
opacity: 1,
filter: 'blur(0px)'
}"
:transition="{
duration: 0.6,
delay: 0.3
}"
>
{{ page.description }}
</Motion>
</template>
</UPageHero>
<UPageSection
:ui="{
container: '!pt-0 lg:grid lg:grid-cols-2 lg:gap-16'
}"
>
<LandingAbout :page />
<LandingClubs :page />
</UPageSection>
<UPageSection
:ui="{
container: '!pt-0'
}"
>
<MDC
:value="page.content"
unwrap="p"
/>
<div class="flex flex-row justify-center items-center py-10 space-x-[-2rem]">
<PolaroidItem
v-for="(image, index) in page.images"
:key="index"
:image="image"
:index
/>
</div>
<LandingEvents :page />
</UPageSection>
</UPage>
</template>
2 changes: 1 addition & 1 deletion app/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ useSeoMeta({
}"
>
<LandingAbout :page />
<LandingWorkExperience :page />
<LandingClubs :page />
</UPageSection>
<LandingBlog :page />
<LandingTestimonials :page />
Expand Down
22 changes: 21 additions & 1 deletion content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,28 @@ export default defineContentConfig({
type: 'page',
source: 'about.yml',
schema: z.object({
about: createBaseSchema(),
experience: createBaseSchema().extend({
items: z.array(z.object({
date: z.date(),
position: z.string(),
company: z.object({
name: z.string(),
url: z.string(),
logo: z.string().editor({ input: 'icon' }),
color: z.string()
})
}))
}),
content: z.object({}),
images: z.array(createImageSchema())
images: z.array(createImageSchema()),
achievements: z.array(z.object({
category: z.enum(['Programación', 'Análisis de Datos', 'Desarrollo Web']),
title: z.string(),
date: z.date(),
description: z.string(),
certificateUrl: z.string().optional()
}))
})
})
}
Expand Down
Loading