e572af0771
- Remove hardcoded startDate from La Porra project - Add gitRepoUrl field to Project struct for dynamic date fetching - Implement backend logic to fetch first commit date from git repositories - Add processProjectDates function to calculate dates dynamically - Update template to display computed dates and dynamic "Present/Presente" - Add support for both static and git-based project start dates When a project has a gitRepoUrl, the system automatically fetches the first commit date from the repository. For current projects, it displays "Present" (English) or "Presente" (Spanish) dynamically from the backend. The La Porra project now uses git repository path for date calculation instead of hardcoded JSON values.
192 lines
6.4 KiB
Go
192 lines
6.4 KiB
Go
package models
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
// CV represents the complete curriculum vitae structure
|
|
type CV struct {
|
|
Personal Personal `json:"personal"`
|
|
Summary string `json:"summary"`
|
|
Experience []Experience `json:"experience"`
|
|
AIDevelopment AIDevelopment `json:"ai_development"`
|
|
Education []Education `json:"education"`
|
|
Skills Skills `json:"skills"`
|
|
Languages []Language `json:"languages"`
|
|
Projects []Project `json:"projects"`
|
|
Awards []Award `json:"awards"`
|
|
Certifications []Certification `json:"certifications"`
|
|
Courses []Course `json:"courses"`
|
|
References []Reference `json:"references"`
|
|
Other Other `json:"other"`
|
|
Meta Meta `json:"meta"`
|
|
}
|
|
|
|
type Personal struct {
|
|
Name string `json:"name"`
|
|
Title string `json:"title"`
|
|
Location string `json:"location"`
|
|
Email string `json:"email"`
|
|
Phone string `json:"phone"`
|
|
DateOfBirth string `json:"dateOfBirth"`
|
|
PlaceOfBirth string `json:"placeOfBirth"`
|
|
Citizenship string `json:"citizenship"`
|
|
LinkedIn string `json:"linkedin"`
|
|
GitHub string `json:"github"`
|
|
Domestika string `json:"domestika"`
|
|
Website string `json:"website"`
|
|
Photo string `json:"photo"`
|
|
}
|
|
|
|
type Experience struct {
|
|
Position string `json:"position"`
|
|
Company string `json:"company"`
|
|
CompanyURL string `json:"companyURL,omitempty"` // Optional URL for company website
|
|
CompanyLogo string `json:"companyLogo"`
|
|
Location string `json:"location"`
|
|
StartDate string `json:"startDate"`
|
|
EndDate string `json:"endDate"`
|
|
Current bool `json:"current"`
|
|
Expired bool `json:"expired,omitempty"` // Optional flag for expired companies
|
|
ShortDescription string `json:"shortDescription"`
|
|
Responsibilities []string `json:"responsibilities"`
|
|
Technologies []string `json:"technologies"`
|
|
Highlights []string `json:"highlights"`
|
|
Duration string `json:"-"` // Calculated field, not from JSON
|
|
}
|
|
|
|
type AIDevelopment struct {
|
|
Title string `json:"title"`
|
|
Period string `json:"period"`
|
|
Description string `json:"description"`
|
|
Skills []AISkill `json:"skills"`
|
|
Achievements []string `json:"achievements"`
|
|
}
|
|
|
|
type AISkill struct {
|
|
Category string `json:"category"`
|
|
Proficiency string `json:"proficiency"`
|
|
Items []string `json:"items"`
|
|
}
|
|
|
|
type Education struct {
|
|
Degree string `json:"degree"`
|
|
Institution string `json:"institution"`
|
|
Location string `json:"location"`
|
|
StartDate string `json:"startDate"`
|
|
EndDate string `json:"endDate"`
|
|
Field string `json:"field"`
|
|
}
|
|
|
|
type Skills struct {
|
|
Technical []SkillCategory `json:"technical"`
|
|
SoftSkills []string `json:"soft_skills"`
|
|
}
|
|
|
|
type SkillCategory struct {
|
|
Category string `json:"category"`
|
|
Proficiency int `json:"proficiency"`
|
|
Items []string `json:"items"`
|
|
Sidebar string `json:"sidebar"` // "left" or "right"
|
|
}
|
|
|
|
type Language struct {
|
|
Language string `json:"language"`
|
|
Proficiency string `json:"proficiency"`
|
|
Level int `json:"level"`
|
|
Detail string `json:"detail,omitempty"` // Optional detail like "Oral (Medio/Alto) Escrito (Alto)"
|
|
}
|
|
|
|
type Project struct {
|
|
Title string `json:"title"`
|
|
URL string `json:"url"`
|
|
ProjectLogo string `json:"projectLogo,omitempty"` // Optional logo filename
|
|
GitRepoUrl string `json:"gitRepoUrl,omitempty"` // Optional git repository URL for dynamic dates
|
|
Location string `json:"location"`
|
|
StartDate string `json:"startDate,omitempty"` // Optional static start date
|
|
Current bool `json:"current"`
|
|
MaintainedBy string `json:"maintainedBy,omitempty"` // Optional maintainer name (e.g., "SAP")
|
|
Technologies []string `json:"technologies"`
|
|
ShortDescription string `json:"shortDescription"`
|
|
Responsibilities []string `json:"responsibilities"`
|
|
|
|
// Computed fields (not stored in JSON)
|
|
ComputedStartDate string `json:"-"` // Dynamically calculated from git repo or system
|
|
DynamicDate string `json:"-"` // Current date for ongoing projects
|
|
}
|
|
|
|
type Award struct {
|
|
Title string `json:"title"`
|
|
Issuer string `json:"issuer"`
|
|
Date string `json:"date"`
|
|
Description string `json:"description"`
|
|
ShortDescription string `json:"shortDescription,omitempty"`
|
|
Responsibilities []string `json:"responsibilities,omitempty"`
|
|
AwardLogo string `json:"awardLogo"`
|
|
}
|
|
|
|
type Certification struct {
|
|
Name string `json:"name"`
|
|
Issuer string `json:"issuer"`
|
|
Date string `json:"date"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
type Course struct {
|
|
Title string `json:"title"`
|
|
Institution string `json:"institution"`
|
|
Location string `json:"location"`
|
|
Date string `json:"date"`
|
|
Duration string `json:"duration"`
|
|
Description string `json:"description"`
|
|
ShortDescription string `json:"shortDescription,omitempty"`
|
|
Responsibilities []string `json:"responsibilities,omitempty"`
|
|
}
|
|
|
|
type Reference struct {
|
|
Title string `json:"title"`
|
|
URL string `json:"url"`
|
|
Type string `json:"type"` // "recommendation", "portfolio", "profile", "cv", "presentation"
|
|
TextBefore string `json:"textBefore,omitempty"` // Text before the link
|
|
LinkText string `json:"linkText,omitempty"` // Bold text inside the link
|
|
TextAfter string `json:"textAfter,omitempty"` // Text after the link
|
|
}
|
|
|
|
type Other struct {
|
|
DriverLicense string `json:"driverLicense"`
|
|
}
|
|
|
|
type Meta struct {
|
|
Version string `json:"version"`
|
|
LastUpdated string `json:"lastUpdated"`
|
|
Format string `json:"format"`
|
|
Language string `json:"language"`
|
|
}
|
|
|
|
// LoadCV loads CV data from a JSON file for the specified language
|
|
func LoadCV(lang string) (*CV, error) {
|
|
// Validate language
|
|
if lang != "en" && lang != "es" {
|
|
return nil, fmt.Errorf("unsupported language: %s", lang)
|
|
}
|
|
|
|
// Determine which JSON file to load
|
|
filename := fmt.Sprintf("data/cv-%s.json", lang)
|
|
|
|
// Read the JSON file
|
|
data, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error reading file %s: %w", filename, err)
|
|
}
|
|
|
|
// Parse JSON
|
|
var cv CV
|
|
if err := json.Unmarshal(data, &cv); err != nil {
|
|
return nil, fmt.Errorf("error parsing JSON: %w", err)
|
|
}
|
|
|
|
return &cv, nil
|
|
}
|