Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ”€ :: 학생 정보 λ””ν…ŒμΌ νŽ˜μ΄μ§€μ— ν”„λ‘œμ νŠΈ UI μΆ”κ°€ #236

Merged
merged 5 commits into from
Jul 29, 2023
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public struct ProjectEntity: Equatable {
public struct ProjectEntity: Equatable, Hashable {
public let name: String
public let iconImageURL: String
public let previewImageURLs: [String]
Expand Down Expand Up @@ -30,7 +30,7 @@ public struct ProjectEntity: Equatable {
}

public extension ProjectEntity {
struct LinkEntity: Equatable {
struct LinkEntity: Equatable, Hashable {
public let name: String
public let url: String

Expand All @@ -40,7 +40,7 @@ public extension ProjectEntity {
}
}

struct InProgressEntity: Equatable {
struct InProgressEntity: Equatable, Hashable {
public let start: String
public let end: String?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ struct StudentDetailView: View {
dismiss()
}
}
.statusBarHidden(true)
.animation(.easeIn, value: state.studentDetailEntity)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
Expand Down Expand Up @@ -221,6 +222,13 @@ struct StudentDetailView: View {
}
}
.studentDetailTitleWrapper(title: "μˆ˜μƒ")

VStack(spacing: 32) {
ForEach(studentDetail?.projects ?? [], id: \.self) { project in
ProjectRowView(project: project)
}
}
.studentDetailTitleWrapper(title: "ν”„λ‘œμ νŠΈ")
}

Color.sms(.system(.white))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import DesignSystem
import NukeUI
import StudentDomainInterface
import SwiftUI

@MainActor
struct ProjectRowView: View {
let project: ProjectEntity
@Environment(\.openURL) var openURL

init(project: ProjectEntity) {
self.project = project
}

var body: some View {
VStack(spacing: 24) {
projectHeaderSection()
projectPreviewsSection()
projectTechStacksSection()
projectMyActivitySection()
projectRelatedLinksSection()
}
}

@ViewBuilder
func projectHeaderSection() -> some View {
HStack(spacing: 8) {
LazyImage(url: URL(string: project.iconImageURL)) { phase in
if let image = phase.image {
image
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(8)
} else {
Color.sms(.neutral(.n30))
.frame(width: 40, height: 40)
.cornerRadius(8)
}
}

VStack(alignment: .leading, spacing: 4) {
SMSText(project.name, font: .body1)
.foregroundColor(.sms(.system(.black)))

let startString = project.inProgress.start
let endString = project.inProgress.end ?? "진행 쀑"
SMSText("\(startString) ~ \(endString)", font: .caption2)
.foregroundColor(.sms(.system(.black)))
}

Spacer()
}
}

@ViewBuilder
func projectPreviewsSection() -> some View {
let rows = [GridItem(.flexible()), .init(.flexible())]
LazyVGrid(columns: rows, spacing: 9) {
ForEach(project.previewImageURLs, id: \.self) { preview in
LazyImage(url: URL(string: preview)) { phase in
if let image = phase.image {
image
.resizable()
.aspectRatio(1, contentMode: .fit)
.cornerRadius(8)
} else {
Color.sms(.neutral(.n30))
.cornerRadius(8)
}
}
}
}
}

@ViewBuilder
func projectTechStacksSection() -> some View {
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 4) {
ForEach(project.techStacks, id: \.self) { techStack in
SMSText(techStack, font: .caption2)
.padding(.horizontal, 12)
.padding(.vertical, 6.5)
.background {
RoundedRectangle(cornerRadius: 8)
.fill(Color.sms(.neutral(.n10)))
}
}
}
}
}

@ViewBuilder
func projectMyActivitySection() -> some View {
SMSText(project.myActivity, font: .body2)
.lineLimit(nil)
.aligned(.leading)
}

@ViewBuilder
func projectRelatedLinksSection() -> some View {
VStack(spacing: 8) {
ForEach(project.links, id: \.self) { link in
HStack(alignment: .top) {
VStack(alignment: .leading, spacing: 8) {
SMSText(link.name, font: .body1)
.foregroundColor(.sms(.system(.black)))

SMSText(link.url, font: .caption2)
.foregroundColor(.sms(.neutral(.n40)))
}

Spacer()

Image(systemName: "arrow.up.right")
.resizable()
.frame(width: 10, height: 10)
.foregroundColor(.sms(.neutral(.n40)))
}
.frame(maxWidth: .infinity)
.padding(8)
.background {
RoundedRectangle(cornerRadius: 8)
.fill(Color.sms(.neutral(.n10)))
}
.buttonWrapper {
guard let url = URL(string: link.url) else { return }
openURL(url)
}
}
}
}
}