First version

This commit is contained in:
Christoph Hagen
2023-08-18 22:47:24 +02:00
parent 1d6e36e2de
commit bd87a4fb6f
48 changed files with 1453 additions and 30 deletions

View File

@ -0,0 +1,45 @@
import SwiftUI
struct TitledCareerSection: View {
let style: CVStyle.Section
let content: Titled<CareerStation>
var body: some View {
TitledSection(title: content.title, spacing: style.titleSpacing) {
ForEach(content.items) { item in
CareerStationView(
info: item,
borderSpacing: style.borderSpacing,
borderWidth: style.borderWidth)
.padding(.bottom, style.bottomSpacing)
}
}
}
}
struct TitledItemSection_Previews: PreviewProvider {
static var previews: some View {
TitledCareerSection(
style: .init(),
content: .init(
title: "Work experience",
items: [
.init(
time: "Jul 2020 - Jul 2023",
location: "Braunschweig, Germany",
title: "German Aerospace Center",
subtitle: "Systems engineer",
text: "Responsible for aircraft systems and avionics of a high-altitude solar drone, safety, and software."),
.init(
time: "Jul 2020 - Jul 2023",
location: "Braunschweig, Germany",
title: "German Aerospace Center",
subtitle: "Systems engineer",
text: "Responsible for aircraft systems and avionics of a high-altitude solar drone, safety, and software.")
])
)
.previewLayout(.fixed(width: 350, height: 400))
}
}

View File

@ -0,0 +1,63 @@
import SwiftUI
extension String: Identifiable {
public var id: String {
self
}
}
extension View {
public func addBorder<S>(_ content: S, width: CGFloat = 1, cornerRadius: CGFloat) -> some View where S : ShapeStyle {
let roundedRect = RoundedRectangle(cornerRadius: cornerRadius)
return clipShape(roundedRect)
.overlay(roundedRect.strokeBorder(content, lineWidth: width))
}
}
struct TitledIconSection: View {
let content: Titled<SkillsSet>
let titleSpacing: CGFloat
let width: CGFloat
let style: SkillStyle
var body: some View {
TitledSection(title: content.title, spacing: titleSpacing) {
VStack(alignment: .leading) {
ForEach(content.items) { item in
HStack(alignment: .firstTextBaseline) {
Image(systemSymbol: item.systemSymbol)
.frame(
width: style.iconSize,
height: style.iconSize)
.padding(.leading, style.horizontalGap)
FlowLayout(alignment: .leading, spacing: style.verticalTagSpacing) {
ForEach(item.entries) { tag in
TagView(
tag,
rounding: style.tagRounding,
color: style.tagBackground)
}
}
}.padding(.bottom, style.rowSpacing)
}
}
}
}
}
struct TitledIconSection_Previews: PreviewProvider {
static var previews: some View {
TitledIconSection(
content: .init(title: "Title", items: [
.init(systemSymbol: .keyboard, entries: ["Swift", "C", "C++", "Python"])
]),
titleSpacing: 10,
width: 200, style: SkillStyle())
.previewLayout(.fixed(width: 230, height: 300))
}
}

View File

@ -0,0 +1,32 @@
import SwiftUI
struct TitledTextSection: View {
let content: Titled<String>
let titleSpacing: CGFloat
let paragraphSpacing: CGFloat
var body: some View {
TitledSection(title: content.title, spacing: titleSpacing) {
ForEach(content.items) { text in
Text(text)
.font(.body)
.fontWeight(.light)
.padding(.bottom, paragraphSpacing)
}
}
}
}
struct TitledTextSection_Previews: PreviewProvider {
static var previews: some View {
TitledTextSection(
content: .init(
title: "Title",
items: ["Some longer or shorter text to explain some feature."]),
titleSpacing: 10,
paragraphSpacing: 5)
}
}

View File

@ -0,0 +1,76 @@
import SwiftUI
import SFSafeSymbols
struct TopView: View {
let info: TopInfo
let style: HeaderStyle
var body: some View {
GeometryReader { geo in
let sideWidth = max(0, (geo.size.width - geo.size.height) / 2)
HStack(spacing: 0) {
VStack(alignment: .leading, spacing: 0) {
Text(info.name)
.font(.title)
.foregroundColor(.accentColor)
Spacer(minLength: 0)
Text(info.tagLine)
.font(.subheadline)
.padding(.trailing, style.imageShadowSize)
Spacer(minLength: 0)
HStack {
RightImageLabel(info.place, systemSymbol: .house)
.padding(.leading, -4)
RightImageLabel(info.ageText, systemSymbol: .hourglass)
}.font(.subheadline)
}
.frame(width: sideWidth)
TopViewImage(
image: info.imageName,
shadow: style.imageShadowSize,
lineWidth: style.imageBorderWidth)
VStack(alignment: .trailing) {
LeftImageLabel(info.web, systemSymbol: .globe)
.frame(maxHeight: style.iconHeight)
Spacer()
LeftImageLabel(info.email, systemSymbol: .envelope)
.frame(maxHeight: style.iconHeight)
Spacer()
LeftImageLabel(info.phone, systemSymbol: .phone)
.frame(maxHeight: style.iconHeight)
Spacer()
HStack(spacing: 0) {
Spacer()
Text(info.github)
Image("Github")
.resizable()
.aspectRatio(1.0, contentMode: .fit)
.padding(2)
.frame(width: style.iconHeight)
}.frame(maxHeight: style.iconHeight)
}
.font(.subheadline)
.frame(width: sideWidth)
}
}
}
}
struct TopView_Previews: PreviewProvider {
static var previews: some View {
TopView(info: .init(
imageName: "Cover",
name: "Christoph Hagen",
tagLine: "Problem solver and creative mind with a favour for interdisciplinary work.",
place: "Würzburg, Germany",
ageText: "Age 32",
web: "christophhagen.de",
email: "jobs@christophhagen.de",
phone: "Upon Request",
github: "github.com/christophhagen"),
style: HeaderStyle())
.previewLayout(.fixed(width: 540, height: 120))
}
}