107 lines
3.8 KiB
Swift
107 lines
3.8 KiB
Swift
import SwiftUI
|
|
import SFSafeSymbols
|
|
import PhoneNumberKit
|
|
|
|
private let emailPattern = #"^\S+@\S+\.\S+$"#
|
|
|
|
struct TopView: View {
|
|
|
|
let info: TopInfo
|
|
|
|
let style: HeaderStyle
|
|
|
|
let accent: Color
|
|
|
|
private let phoneNumberKit = PhoneNumberKit()
|
|
|
|
var isValidEmail: Bool {
|
|
info.email.range(of: emailPattern, options: .regularExpression) != nil
|
|
}
|
|
|
|
var isValidPhoneNumber: Bool {
|
|
do {
|
|
_ = try phoneNumberKit.parse(info.phone)
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
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(accent)
|
|
Spacer(minLength: 0)
|
|
Text(info.tagLine)
|
|
.font(.subheadline)
|
|
.padding(.trailing, style.imageShadowSize)
|
|
Spacer(minLength: 0)
|
|
HStack {
|
|
RightImageLabel(info.place, systemSymbol: .house)
|
|
RightImageLabel(info.ageText, systemSymbol: .hourglass)
|
|
Spacer()
|
|
}.font(.subheadline)
|
|
}
|
|
.frame(width: sideWidth)
|
|
TopViewImage(
|
|
image: info.imageName,
|
|
shadow: style.imageShadowSize,
|
|
lineWidth: style.imageBorderWidth)
|
|
VStack(alignment: .trailing) {
|
|
LeftImageLabel(systemSymbol: .globe) {
|
|
Link(info.web, destination: URL(string: "https://" + info.web)!)
|
|
}
|
|
.frame(maxHeight: style.iconHeight)
|
|
Spacer()
|
|
LeftImageLabel(systemSymbol: .envelope) {
|
|
Link(info.email, destination: URL(string: "mailto:" + info.email)!)
|
|
.disabled(!isValidEmail)
|
|
}
|
|
.frame(maxHeight: style.iconHeight)
|
|
Spacer()
|
|
LeftImageLabel(systemSymbol: .phone) {
|
|
Link(info.phone, destination: URL(string: "tel:" + info.phone)!)
|
|
.disabled(!isValidPhoneNumber)
|
|
}
|
|
.frame(maxHeight: style.iconHeight)
|
|
Spacer()
|
|
HStack(spacing: 0) {
|
|
Spacer()
|
|
Link(info.github, destination: URL(string: "https://" + 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)
|
|
.foregroundStyle(.primary)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct TopView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
TopView(info: .init(
|
|
imageName: "Cover",
|
|
name: "Christoph Hagen",
|
|
tagLine: "Problem solver 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(),
|
|
accent: .orange)
|
|
.previewLayout(.fixed(width: 540, height: 120))
|
|
}
|
|
}
|