Add the section content models (Hero, About, Skills, Projects, Goals, Experience, Documents, Contact) with per-field character limits
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>Bereich "Ueber mich" (section id="about").</summary>
|
||||
public class AboutSection
|
||||
{
|
||||
[StringLength(ContentLimits.Url, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Image { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.AltText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string ImageAlt { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleLine1 { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleLine2 { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Hervorgehobener Teil der zweiten Titelzeile.</summary>
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleLine2Highlight { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.ParagraphText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
public List<FactItem> Facts { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>Eine Zeile der Kurzuebersicht rechts unter dem Text.</summary>
|
||||
public class FactItem
|
||||
{
|
||||
[StringLength(ContentLimits.FactLabel, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Label { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.FactValue, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Value { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>
|
||||
/// Bereich "Kontakt" (section id="contact"). Enthaelt nur die Texte;
|
||||
/// das Formular selbst bleibt Bestandteil der Seite und ist nicht editierbar.
|
||||
/// </summary>
|
||||
public class ContactSection
|
||||
{
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleHighlight { get; set; } = string.Empty;
|
||||
|
||||
public List<ContactInfoItem> InfoBoxes { get; set; } = new();
|
||||
|
||||
/// <summary>Einleitungstext oberhalb der Formularfelder.</summary>
|
||||
[StringLength(ContentLimits.FormIntro, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string FormHeading { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>Eine Kontaktangabe (Standort, Telefon, E-Mail, ...).</summary>
|
||||
public class ContactInfoItem
|
||||
{
|
||||
/// <summary>CSS-Klasse des Icons, z. B. "flaticon-call".</summary>
|
||||
[StringLength(ContentLimits.IconClass, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Icon { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.FactLabel, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.FactValue, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Optional: macht den Text zum Link, z. B. "tel:0797367355".</summary>
|
||||
[StringLength(ContentLimits.Url, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string LinkUrl { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>Bereich "Dokumente und Zertifikate" (section id="documents").</summary>
|
||||
public class DocumentsSection
|
||||
{
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleHighlight { get; set; } = string.Empty;
|
||||
|
||||
public List<DocumentItem> Items { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>Ein Dokument bzw. Zertifikat mit Link auf die PDF-Datei.</summary>
|
||||
public class DocumentItem
|
||||
{
|
||||
[StringLength(ContentLimits.CardTitle, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.ParagraphText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Url, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string FileUrl { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.ButtonLabel, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string LinkText { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>Bereich "Berufliche Erfahrung" (section id="experience").</summary>
|
||||
public class ExperienceSection
|
||||
{
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleHighlight { get; set; } = string.Empty;
|
||||
|
||||
public List<ExperienceItem> Items { get; set; } = new();
|
||||
|
||||
[StringLength(ContentLimits.ButtonLabel, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string ToggleMoreText { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.ButtonLabel, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string ToggleLessText { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>Ein Eintrag der Erfahrungs-Timeline.</summary>
|
||||
public class ExperienceItem
|
||||
{
|
||||
[StringLength(ContentLimits.CardTitle, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Meta, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Meta { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.DetailHeading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string DetailHeading { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.ParagraphText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>true = erst nach Klick auf "Mehr erfahren" sichtbar.</summary>
|
||||
public bool Collapsed { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>Bereich "Meine Ziele" (section id="goals").</summary>
|
||||
public class GoalsSection
|
||||
{
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleHighlight { get; set; } = string.Empty;
|
||||
|
||||
public List<GoalItem> Items { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>Eine Ziel-Kachel.</summary>
|
||||
public class GoalItem
|
||||
{
|
||||
/// <summary>CSS-Klasse des Icons, z. B. "flaticon-growth".</summary>
|
||||
[StringLength(ContentLimits.IconClass, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Icon { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.TileTitle, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.TileText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>true = hervorgehobene Kachel (CSS-Klasse "active").</summary>
|
||||
public bool Highlighted { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>Startbereich der Seite (section id="hero").</summary>
|
||||
public class HeroSection : IValidatableObject
|
||||
{
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Grosse Titelzeilen. Die letzte Zeile wird farblich hervorgehoben.</summary>
|
||||
public List<string> TitleLines { get; set; } = new();
|
||||
|
||||
[StringLength(ContentLimits.ParagraphText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Intro { get; set; } = string.Empty;
|
||||
|
||||
public LinkItem PrimaryButton { get; set; } = new();
|
||||
public LinkItem SecondaryButton { get; set; } = new();
|
||||
|
||||
/// <summary>Kleine Links unter den Buttons (LinkedIn, E-Mail, ...).</summary>
|
||||
public List<LinkItem> SocialLinks { get; set; } = new();
|
||||
|
||||
[StringLength(ContentLimits.Url, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string PortraitImage { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.AltText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string PortraitAlt { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Prueft die Titelzeilen einzeln: [StringLength] laesst sich nicht direkt
|
||||
/// auf eine List<string> anwenden, deshalb hier von Hand.
|
||||
/// </summary>
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
for (var i = 0; i < TitleLines.Count; i++)
|
||||
{
|
||||
if (TitleLines[i]?.Length > ContentLimits.Heading)
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
$"Titelzeile {i + 1} darf höchstens {ContentLimits.Heading} Zeichen lang sein.",
|
||||
[nameof(TitleLines)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>Bereich "Projekte" (section id="projects").</summary>
|
||||
public class ProjectsSection
|
||||
{
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleHighlight { get; set; } = string.Empty;
|
||||
|
||||
public List<ProjectItem> Items { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>Eine Projektkarte.</summary>
|
||||
public class ProjectItem
|
||||
{
|
||||
[StringLength(ContentLimits.Url, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Image { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.AltText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string ImageAlt { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.CardTitle, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Optionaler fett gesetzter Auftakt vor der Beschreibung, z. B. "Ziel:".</summary>
|
||||
[StringLength(ContentLimits.DetailHeading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string DescriptionLead { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.ParagraphText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Zwischentitel mit Text ("TECH:", "Meine Arbeit:", ...).</summary>
|
||||
public List<DetailBlock> Details { get; set; } = new();
|
||||
|
||||
public List<LinkItem> Links { get; set; } = new();
|
||||
|
||||
/// <summary>true = breite Karte ueber die volle Breite mit Bild links.</summary>
|
||||
public bool Wide { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>Bereich "Kompetenzen" (section id="skills").</summary>
|
||||
public class SkillsSection
|
||||
{
|
||||
[StringLength(ContentLimits.Kicker, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Kicker { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Hervorgehobener Teil des Titels.</summary>
|
||||
[StringLength(ContentLimits.Heading, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string TitleHighlight { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.ParagraphText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Intro { get; set; } = string.Empty;
|
||||
|
||||
public List<SkillItem> Items { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>Eine Kompetenz-Kachel.</summary>
|
||||
public class SkillItem
|
||||
{
|
||||
/// <summary>CSS-Klasse des Icons, z. B. "flaticon-pen".</summary>
|
||||
[StringLength(ContentLimits.IconClass, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Icon { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.TileTitle, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(ContentLimits.TileText, ErrorMessage = ContentLimits.TooLongMessage)]
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>true = hervorgehobene Kachel (CSS-Klasse "active").</summary>
|
||||
public bool Highlighted { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user