Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion IT-DA-iOS/App/IT_DA_iOSApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import SwiftUI
struct IT_DA_iOSApp: App {
var body: some Scene {
WindowGroup {
ContentView()
MainTabView()
}
}
}
170 changes: 168 additions & 2 deletions IT-DA-iOS/Features/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,177 @@
import SwiftUI

struct HomeView: View {
@Binding var selectedTab: ITDATab

var body: some View {
VStack(spacing: 0) {
ITDAScreenHeader(title: "Home")

ScrollView(showsIndicators: false) {
VStack(alignment: .leading, spacing: 0) {
profileHeader
.padding(.top, 30)

StatusSummaryBoxView(applyCount: 3, joinCount: 1, doneCount: 1)
.padding(.top, 22)

sectionTitle("추천 프로젝트")
.padding(.top, 28)

VStack(spacing: 18) {
ProjectCardView(
title: "AI 기반 학습 플래너 [아부부]",
subtitle: "백엔드 개발자 1명 모집",
status: "모집 중",
tags: ["Back-end"],
footnote: "IoT과 · 2명, SW과 1명 참여"
)

ProjectCardView(
title: "하치와레 키우기 [하키]",
subtitle: "프론트엔드 개발자 2명 모집",
status: "모집 중",
tags: ["Back-end"],
footnote: "IoT과 · 2명, SW과 1명 참여"
)

ProjectCardView(
title: "닮은 포켓몬 검사 [포켓몬벽]",
subtitle: "iOS 개발자 · 1명 · 디자이너 1명 모집",
status: "마감 임박",
tags: ["iOS", "Design"],
footnote: "IoT과 · 2명, SW과 1명 참여"
)
}
.padding(.top, 14)

sectionTitle("참여 중인 프로젝트")
.padding(.top, 28)

ProjectCardView(
title: "사랑을 이어주는 앱 [달별]",
subtitle: "내 역할 : iOS 개발",
status: "진행 중",
footnote: "팀원 4명 · 마감 2026-05-31"
)
.padding(.top, 14)

sectionTitle("알림 요약 · 확인")
.padding(.top, 28)

VStack(spacing: 12) {
HomeNotificationRowView(
emoji: "📬",
message: "지원한 프로젝트에서 새 메시지가 있습니다",
timeText: "2분전"
)

HomeNotificationRowView(
emoji: "💻",
message: "백엔드 개발자 1명이 프로젝트에 합류 하였습니다",
timeText: "2분전"
)
}
.padding(.top, 14)

Button {
selectedTab = .notifications
} label: {
Text("모든 알림 보기")
.font(.custom("AstaSans-Medium", size: 12))
.foregroundColor(Color("보조 텍스트"))
.underline()
}
.buttonStyle(.plain)
.padding(.top, 16)

Spacer()
.frame(height: 112)
}
.frame(width: 342, alignment: .leading)
.frame(maxWidth: .infinity)
}
}
.background(.white)
}

private var profileHeader: some View {
HStack(spacing: 13) {
ZStack {
Circle()
.fill(Color("구분선").opacity(0.6))

VStack(spacing: 0) {
Circle()
.fill(Color("기본 텍스트"))
.frame(width: 25, height: 25)

Ellipse()
.fill(Color("기본 텍스트"))
.frame(width: 48, height: 24)
.offset(y: 3)
}
.offset(y: 7)
.clipShape(Circle())
}
.frame(width: 58, height: 58)

VStack(alignment: .leading, spacing: 6) {
Text("안녕하세요, 000님 👋")
.font(.custom("AstaSans-Bold", size: 20))
.foregroundColor(Color("기본 텍스트"))

Text("상상은 여기서 현실이 됩니다.\n당신의 프로젝트와 팀을 찾아보세요")
.font(.custom("AstaSans-Medium", size: 12))
.foregroundColor(Color("보조 텍스트"))
.lineSpacing(2)
}
}
}

private func sectionTitle(_ title: String) -> some View {
Text(title)
.font(.custom("AstaSans-Bold", size: 20))
.foregroundColor(Color("기본 텍스트"))
}
}

private struct HomeNotificationRowView: View {
let emoji: String
let message: String
let timeText: String

var body: some View {
Color.white
HStack(spacing: 14) {
Text(emoji)
.font(.system(size: 30))
.frame(width: 42)

VStack(alignment: .leading, spacing: 8) {
Text(message)
.font(.custom("AstaSans-Medium", size: 13))
.foregroundColor(Color("보조 텍스트"))
.lineLimit(1)
.minimumScaleFactor(0.85)

Text(timeText)
.font(.custom("AstaSans-Medium", size: 12))
.foregroundColor(Color("보조 텍스트"))
}

Spacer()
}
.padding(.horizontal, 18)
.frame(width: 342, height: 72)
.background(.white)
.cornerRadius(10)
.overlay {
RoundedRectangle(cornerRadius: 10)
.stroke(Color("구분선"), lineWidth: 1)
}
}
}

#Preview {
HomeView()
HomeView(selectedTab: .constant(.home))
}
93 changes: 93 additions & 0 deletions IT-DA-iOS/Features/Notification/NotificationView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//
// NotificationView.swift
// IT-DA-iOS
//
// Created by Codex on 6/6/26.
//

import SwiftUI

struct NotificationView: View {
@Binding var selectedTab: ITDATab
@State private var selectedFilter = "전체"

private let notifications = [
NotificationItem(title: "새 프로젝트 추천", message: "나의 기술 스택과 일치하는 프로그램이 등록되었습니다.", isRead: false, timeText: "5분 전"),
NotificationItem(title: "지원 결과 도착", message: "백엔드 개발자 1명이 팀에 합류했습니다.", isRead: false, timeText: "1시간 전"),
NotificationItem(title: "팀 멤버 합류", message: "백엔드 개발자 1명이 팀에 합류했습니다.", isRead: true, timeText: "1시간 전"),
NotificationItem(title: "새 프로젝트 추천", message: "관심 분야 추천 프로젝트가 새로 업데이트 되었습니다.", isRead: true, timeText: "1시간 전")
]

var body: some View {
VStack(spacing: 0) {
ITDAScreenHeader(
title: "알림",
showsBackButton: true,
trailingTitle: "전체 읽음 처리",
backAction: { selectedTab = .home }
)

ScrollView(showsIndicators: false) {
VStack(alignment: .leading, spacing: 12) {
Text("알림")
.font(.custom("AstaSans-Bold", size: 24))
.foregroundColor(.black)
.padding(.top, 22)

Text("알림 유형")
.font(.custom("AstaSans-Medium", size: 14))
.foregroundColor(Color("구분선"))
.padding(.top, 12)

SelectboxView(
placeholder: "전체",
options: ["전체", "안 읽음", "읽음"],
selected: $selectedFilter
)
.zIndex(10)

VStack(spacing: 12) {
ForEach(filteredNotifications) { item in
NewProjectBoxView(
title: item.title,
message: item.message,
isRead: item.isRead,
timeText: item.timeText
)
}
}
.padding(.top, 2)

Spacer()
.frame(height: 112)
}
.frame(width: 342, alignment: .leading)
.frame(maxWidth: .infinity)
}
}
.background(.white)
}

private var filteredNotifications: [NotificationItem] {
switch selectedFilter {
case "안 읽음":
notifications.filter { !$0.isRead }
case "읽음":
notifications.filter { $0.isRead }
default:
notifications
}
}
}

private struct NotificationItem: Identifiable {
let id = UUID()
let title: String
let message: String
let isRead: Bool
let timeText: String
}

#Preview {
NotificationView(selectedTab: .constant(.notifications))
}
73 changes: 73 additions & 0 deletions IT-DA-iOS/Shared/Components/Layout/ITDAScreenHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// ITDAScreenHeader.swift
// IT-DA-iOS
//
// Created by Codex on 6/6/26.
//

import SwiftUI

struct ITDAScreenHeader: View {
let title: String
var showsBackButton = false
var trailingTitle: String?
var backAction: () -> Void = {}
var trailingAction: () -> Void = {}

var body: some View {
VStack(spacing: 0) {
ZStack {
if showsBackButton {
Button(action: backAction) {
Image(systemName: "chevron.left")
.font(.system(size: 22, weight: .medium))
.foregroundColor(.black)
.frame(width: 44, height: 44)
.background(Circle().fill(.white))
.shadow(color: .black.opacity(0.06), radius: 10, x: 0, y: 4)
}
.buttonStyle(.plain)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.leading, 28)
}

Text(title)
.font(.custom("AstaSans-Bold", size: 22))
.foregroundColor(Color("기본 텍스트"))

if let trailingTitle {
Button(action: trailingAction) {
Text(trailingTitle)
.font(.custom("AstaSans-Bold", size: 13))
.foregroundColor(.white)
.padding(.horizontal, 14)
.frame(height: 30)
.background(Color("버튼 배경"))
.cornerRadius(8)
}
.buttonStyle(.plain)
.frame(maxWidth: .infinity, alignment: .trailing)
.padding(.trailing, 28)
}
}
.frame(height: 86)
.padding(.top, 22)

Rectangle()
.fill(Color("구분선").opacity(0.25))
.frame(height: showsBackButton ? 0 : 1)
}
}
}

#Preview {
VStack(spacing: 24) {
ITDAScreenHeader(title: "Home")
ITDAScreenHeader(
title: "알림",
showsBackButton: true,
trailingTitle: "전체 읽음 처리"
)
}
.background(.white)
}
Loading