[✨] 대시보드 학습관리 & 공지사항 뷰 생성, 메인화면 전환 로직 수정
This commit is contained in:
parent
ad85ccea7a
commit
f6a371923a
Binary file not shown.
|
@ -39,7 +39,9 @@ struct SimpleBtnView: View {
|
||||||
if let image = state.image {
|
if let image = state.image {
|
||||||
image
|
image
|
||||||
.resizable()
|
.resizable()
|
||||||
|
.renderingMode(.template)
|
||||||
.frame(width: state.width, height: state.height)
|
.frame(width: state.width, height: state.height)
|
||||||
|
.foregroundStyle(state.isUsable ? Color(.Second.normal) : Color(.Normal.normal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disabled(!state.isUsable)
|
.disabled(!state.isUsable)
|
|
@ -12,22 +12,23 @@ import Combine
|
||||||
/// 이거 위에 다른 뷰들이 위젯 느낌으로 계속 갈아 끼워지는거
|
/// 이거 위에 다른 뷰들이 위젯 느낌으로 계속 갈아 끼워지는거
|
||||||
struct NavigationView: View {
|
struct NavigationView: View {
|
||||||
@EnvironmentObject var appVM: AppViewModel
|
@EnvironmentObject var appVM: AppViewModel
|
||||||
|
|
||||||
@State private var naviState : NaviState = .init(act: .NONE, path: .Intro)
|
@State private var naviState : NaviState = .init(act: .NONE, path: .Intro)
|
||||||
@State private var history: [PathName] = [.Intro]
|
@State private var history: [PathName] = [.Intro]
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
VStack(spacing: 0) {
|
||||||
switch naviState.path {
|
|
||||||
case .NONE:
|
ZStack {
|
||||||
EmptyView()
|
switch naviState.path {
|
||||||
case .Intro:
|
case .NONE:
|
||||||
IntroView(naviState: $naviState)
|
EmptyView()
|
||||||
case .Login :
|
case .Intro:
|
||||||
LoginView(naviState: $naviState)
|
IntroView(naviState: $naviState)
|
||||||
case .Main:
|
case .Login :
|
||||||
MainView(naviState: $naviState)
|
LoginView(naviState: $naviState)
|
||||||
|
case .Main:
|
||||||
|
MainView(naviState: $naviState, menuName: .Home)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: naviState) { old, new in
|
.onChange(of: naviState) { old, new in
|
||||||
|
@ -43,7 +44,6 @@ struct NavigationView: View {
|
||||||
case .MOVE:
|
case .MOVE:
|
||||||
moveHistory(path: new.path)
|
moveHistory(path: new.path)
|
||||||
}
|
}
|
||||||
// LOG
|
|
||||||
printLog("\(old.path) => \(new.path)")
|
printLog("\(old.path) => \(new.path)")
|
||||||
showHistory()
|
showHistory()
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,6 @@ struct OffsetObservableScrollView<Content: View>: View {
|
||||||
Color.clear
|
Color.clear
|
||||||
.frame(height: 1)
|
.frame(height: 1)
|
||||||
.id("TOP")
|
.id("TOP")
|
||||||
|
|
||||||
// 실제 콘텐츠. content 클로저에서 scrollViewProxy를 전달받으므로,
|
|
||||||
// 버튼 등을 통해 프로그래밍적으로 스크롤할 수 있음.
|
|
||||||
content(scrollViewProxy)
|
content(scrollViewProxy)
|
||||||
.overlay {
|
.overlay {
|
||||||
GeometryReader { geometryProxy in
|
GeometryReader { geometryProxy in
|
||||||
|
@ -58,7 +55,7 @@ struct OffsetObservableScrollView<Content: View>: View {
|
||||||
}
|
}
|
||||||
.coordinateSpace(name: coordinateSpaceName)
|
.coordinateSpace(name: coordinateSpaceName)
|
||||||
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
|
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
|
||||||
printLog("\(scrollOffset) -> \(value)")
|
// printLog("\(scrollOffset) -> \(value)")
|
||||||
scrollOffset = value
|
scrollOffset = value
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,26 @@ struct CalendarBoxView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
||||||
DashBoardView(image: Image(.Icon.calendar), title: "최근 일정") {
|
DashBoardView(image: Image(.Icon.calendar), title: "최근 일정") {
|
||||||
VStack(spacing: 12) {
|
if !summaryCalDataList.isEmpty {
|
||||||
ForEach(Array(summaryCalDataList.enumerated()), id: \.offset) { index, data in
|
VStack(spacing: 12) {
|
||||||
CalCellView(summaryCalData: data)
|
ForEach(Array(summaryCalDataList.enumerated()), id: \.offset) { index, data in
|
||||||
|
CalCellView(summaryCalData: data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Text("최근 일정이 없습니다.")
|
||||||
|
.font(.nps(size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
.truncationMode(.tail)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding([.top,.bottom],12)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
.stroke(Color(.Second.normal), lineWidth: 2)
|
||||||
|
.fill(Color(.Second.light))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} moreAction: {
|
} moreAction: {
|
72
AcaMate/1. View/12. Main/121. Home/HomeView.swift
Normal file
72
AcaMate/1. View/12. Main/121. Home/HomeView.swift
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// HomeView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/11/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct HomeView: View {
|
||||||
|
@State private var scrollOffset: CGPoint = .zero
|
||||||
|
@State private var topViewState: Bool = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
ZStack {
|
||||||
|
OffsetObservableScrollView(showsIndicators: false, scrollOffset: $scrollOffset) { proxy in
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
|
||||||
|
TopProfileView(userType: .Student)
|
||||||
|
// .padding(EdgeInsets(top: 0, leading: 0, bottom: 12, trailing: 0))s
|
||||||
|
.padding(.bottom,12)
|
||||||
|
|
||||||
|
Group {
|
||||||
|
AttendanceBoxView()
|
||||||
|
CalendarBoxView(summaryCalDataList: [])
|
||||||
|
CalendarBoxView(summaryCalDataList: [
|
||||||
|
SummaryCalendar(id: "123", date: "2025-02-28", summary: "요약내용입니다."),
|
||||||
|
SummaryCalendar(id: "123", date: "2025-02-28", summary: "요약내용입니다.")])
|
||||||
|
ManagementBoxView(managementList: [])
|
||||||
|
ManagementBoxView(managementList: [
|
||||||
|
SummaryManagement(id: "01", title: "과목 명1", teacher: "A", ratio: 27, homework: 3),
|
||||||
|
SummaryManagement(id: "02", title: "과목 명2", teacher: "B", ratio: 80, homework: 10),
|
||||||
|
SummaryManagement(id: "03", title: "과목 명3", teacher: "C", ratio: 13, homework: 2),
|
||||||
|
SummaryManagement(id: "04", title: "과목 명4", teacher: "D", ratio: 72, homework: 0),
|
||||||
|
])
|
||||||
|
NoticeBoxView(noticeList: [
|
||||||
|
SummaryNotice(id: "00", title: "공지사항1", date: "2025-02-11", new: true),
|
||||||
|
SummaryNotice(id: "01", title: "공지사항2", date: "2025-01-11", new: false),
|
||||||
|
SummaryNotice(id: "02", title: "공지사항3", date: "2025-01-01", new: false)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 8)
|
||||||
|
.foregroundStyle(Color(.Other.cell))
|
||||||
|
}
|
||||||
|
.padding(EdgeInsets(top: 12, leading: 24, bottom: 12, trailing: 24))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if topViewState {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
TopView(titleName: "Name")
|
||||||
|
.transition(.move(edge: .top))
|
||||||
|
.animation(.easeInOut, value: scrollOffset)
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.onChange(of: scrollOffset.y) { oldValue, newValue in
|
||||||
|
if newValue > 200 && topViewState == false {
|
||||||
|
topViewState = true
|
||||||
|
} else if newValue < 20 && topViewState == true{
|
||||||
|
topViewState = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
173
AcaMate/1. View/12. Main/121. Home/ManagementBoxView.swift
Normal file
173
AcaMate/1. View/12. Main/121. Home/ManagementBoxView.swift
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
//
|
||||||
|
// ManagementBoxView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/10/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ManagementBoxView: View {
|
||||||
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
|
@State private var leftBtnID = UUID()
|
||||||
|
@State private var rightBtnID = UUID()
|
||||||
|
@State var managementList: [SummaryManagement]
|
||||||
|
@State private var countNum: Int = 0
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
DashBoardView(image: Image(.Icon.edu), title: "학습 관리") {
|
||||||
|
if managementList.count >= 1 {
|
||||||
|
HStack {
|
||||||
|
SimpleBtnView(vm: btnVM, id: leftBtnID)
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
SimpleBtnView(vm: btnVM, id: rightBtnID)
|
||||||
|
}
|
||||||
|
.padding([.bottom],12)
|
||||||
|
|
||||||
|
MangCellView(summaryMang: $managementList[countNum])
|
||||||
|
} else {
|
||||||
|
Text("학습하고 있는 강의가 없습니다.")
|
||||||
|
.font(.nps(size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
.truncationMode(.tail)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding([.top,.bottom],12)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
.stroke(Color(.Second.normal), lineWidth: 2)
|
||||||
|
.fill(Color(.Second.light))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} moreAction: {
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 학습관리 전체 페이지 이동 로직 추가
|
||||||
|
printLog("학습 관리의 더보기")
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
btnVM.setImage(for: leftBtnID, newImage: Image(.Icon.left))
|
||||||
|
btnVM.setSize(for: leftBtnID, newWidth: 24, newHeight: 24)
|
||||||
|
btnVM.setAction(for: leftBtnID) { countNum -= 1 }
|
||||||
|
btnVM.setIsUsable(for: leftBtnID, newValue: false)
|
||||||
|
|
||||||
|
btnVM.setImage(for: rightBtnID, newImage: Image(.Icon.right))
|
||||||
|
btnVM.setSize(for: rightBtnID, newWidth: 24, newHeight: 24)
|
||||||
|
btnVM.setAction(for: rightBtnID) { countNum += 1 }
|
||||||
|
if managementList.count == 0 {
|
||||||
|
btnVM.setIsUsable(for: rightBtnID, newValue: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.onChange(of: countNum) { oldValue, newValue in
|
||||||
|
if countNum == 0 {
|
||||||
|
btnVM.setIsUsable(for: leftBtnID, newValue: false)
|
||||||
|
|
||||||
|
} else if 0 < countNum && countNum < managementList.count-1 {
|
||||||
|
btnVM.setIsUsable(for: leftBtnID, newValue: true)
|
||||||
|
btnVM.setIsUsable(for: rightBtnID, newValue: true)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
btnVM.setIsUsable(for: rightBtnID, newValue: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MangCellView: View {
|
||||||
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
|
@Binding var summaryMang: SummaryManagement
|
||||||
|
@State var ratioBtn = UUID()
|
||||||
|
@State var flagBtn = UUID()
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
VStack(spacing: 8) {
|
||||||
|
HStack(spacing: 12) {
|
||||||
|
Image(.Icon.management)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 24, height: 24, alignment: .center)
|
||||||
|
Text("\(summaryMang.title)")
|
||||||
|
.font(.nps(size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.title))
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
}
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
Text("\(summaryMang.teacher)")
|
||||||
|
.font(.nps(size: 12))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Text("선생님")
|
||||||
|
.font(.nps(size: 12))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// 상단 내용은 여까지
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
HStack(spacing: 10) {
|
||||||
|
CircleBtnView(vm: btnVM, id: ratioBtn)
|
||||||
|
VStack(spacing: 10) {
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Text("학습")
|
||||||
|
.font(.nps(size: 16))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Text("진도")
|
||||||
|
.font(.nps(font: .bold, size: 16))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
}
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
Text("\(summaryMang.ratio)")
|
||||||
|
.font(.nps(font: .bold, size: 24))
|
||||||
|
.foregroundStyle(summaryMang.ratio > 70 ? Color(.Other.blue):Color(.Other.red))
|
||||||
|
Text("%")
|
||||||
|
.font(.nps(font: .bold, size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VStack(spacing: 10) {
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Text("숙제")
|
||||||
|
.font(.nps(font: .bold, size: 16))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Text("개수")
|
||||||
|
.font(.nps(size: 16))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
}
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
Text("\(summaryMang.homework)")
|
||||||
|
.font(.nps(font: .bold, size: 24))
|
||||||
|
.foregroundStyle(Color(.Second.normal))
|
||||||
|
Text("개")
|
||||||
|
.font(.nps(font: .bold, size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.padding(12)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
.stroke(Color(.Second.normal), lineWidth: 2)
|
||||||
|
.fill(Color(.Second.light))
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 해당 과목의 학습관리 페이지 이동 로직 추가
|
||||||
|
printLog(summaryMang)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
58
AcaMate/1. View/12. Main/121. Home/NoticeBoxView.swift
Normal file
58
AcaMate/1. View/12. Main/121. Home/NoticeBoxView.swift
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// NoticeBoxView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/11/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct NoticeBoxView: View {
|
||||||
|
@State var noticeList: [SummaryNotice]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
DashBoardView(image: Image(.Icon.notice), title: "공지사항") {
|
||||||
|
ForEach(Array(noticeList.enumerated()), id: \.offset) { index, notice in
|
||||||
|
|
||||||
|
if index < 3 {
|
||||||
|
NotiCellView(summaryNoti: notice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 값없을때도 없다는거 보여주는 창 띄우기
|
||||||
|
|
||||||
|
} moreAction: {
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 공지사항 전체 페이지 이동 로직 추가
|
||||||
|
printLog("공지사항의 더보기")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NotiCellView: View {
|
||||||
|
var summaryNoti: SummaryNotice
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 8) {
|
||||||
|
HStack(spacing: 12) {
|
||||||
|
Image(summaryNoti.new ? .Icon.noticeNew : .Icon.noticeOld)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 24, height: 24, alignment: .center)
|
||||||
|
Text("\(summaryNoti.title)")
|
||||||
|
.font(.nps(size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.title))
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
}
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
Text("날짜 :")
|
||||||
|
.font(.nps(size: 12))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Text("\(summaryNoti.date)")
|
||||||
|
.font(.nps(size: 12))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ import SwiftUI
|
||||||
struct TopProfileView: View {
|
struct TopProfileView: View {
|
||||||
@StateObject var btnVM = ButtonViewModel()
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
|
|
||||||
var userType: UserType = .Parent
|
var userType: UserType
|
||||||
|
|
||||||
// MARK: TO-DO
|
// MARK: TO-DO
|
||||||
// 여기서 이름 떙겨오는것도 고민을 해야 함
|
// 여기서 이름 떙겨오는것도 고민을 해야 함
|
||||||
|
@ -81,6 +81,8 @@ struct TopProfileView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.fullDrawView(.Other.cell)
|
.fullDrawView(.Other.cell)
|
||||||
|
|
||||||
|
|
||||||
.onAppear {
|
.onAppear {
|
||||||
let topBtnIDList = [shopID,notifyID]
|
let topBtnIDList = [shopID,notifyID]
|
||||||
let iconList = [Image(.Icon.market), Image(.Icon.notificationSET)]
|
let iconList = [Image(.Icon.market), Image(.Icon.notificationSET)]
|
||||||
|
@ -132,6 +134,3 @@ struct TopProfileView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
|
||||||
TopProfileView()
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
//
|
|
||||||
// ManagementBoxView.swift
|
|
||||||
// AcaMate
|
|
||||||
//
|
|
||||||
// Created by TAnine on 2/10/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct ManagementBoxView: View {
|
|
||||||
@StateObject var btnVM = ButtonViewModel()
|
|
||||||
@State private var leftBtnID = UUID()
|
|
||||||
@State private var rightBtnID = UUID()
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
DashBoardView(image: Image(.Icon.edu), title: "학습 관리") {
|
|
||||||
|
|
||||||
} moreAction: {
|
|
||||||
printLog("학습 관리의 더보기")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MangCellView: View {
|
|
||||||
@StateObject var btnVM = ButtonViewModel()
|
|
||||||
let summaryMang: SummaryManagement
|
|
||||||
@State var ratioBtn = UUID()
|
|
||||||
@State var flagBtn = UUID()
|
|
||||||
var body: some View {
|
|
||||||
VStack(spacing: 8) {
|
|
||||||
HStack(spacing: 12) {
|
|
||||||
Image(.Icon.management)
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 24, height: 24, alignment: .center)
|
|
||||||
Text("\(summaryMang.title)")
|
|
||||||
.font(.nps(size: 20))
|
|
||||||
.foregroundStyle(Color(.Text.title))
|
|
||||||
Spacer(minLength: 1)
|
|
||||||
}
|
|
||||||
HStack(spacing: 4) {
|
|
||||||
Spacer(minLength: 1)
|
|
||||||
Text("\(summaryMang.teacher)")
|
|
||||||
.font(.nps(size: 12))
|
|
||||||
.foregroundStyle(Color(.Text.detail))
|
|
||||||
Text("이름")
|
|
||||||
.font(.nps(size: 12))
|
|
||||||
.foregroundStyle(Color(.Text.detail))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
// 상단 내용은 여까지
|
|
||||||
HStack(spacing: 6) {
|
|
||||||
HStack(spacing: 10) {
|
|
||||||
CircleBtnView(vm: btnVM, id: ratioBtn)
|
|
||||||
VStack(spacing: 10) {
|
|
||||||
HStack(spacing: 4) {
|
|
||||||
Text("학습")
|
|
||||||
.font(.nps(size: 16))
|
|
||||||
.foregroundStyle(Color(.Text.detail))
|
|
||||||
Text("진도")
|
|
||||||
.font(.nps(font: .bold, size: 16))
|
|
||||||
.foregroundStyle(Color(.Text.detail))
|
|
||||||
Spacer(minLength: 1)
|
|
||||||
}
|
|
||||||
HStack(spacing: 4) {
|
|
||||||
Spacer(minLength: 1)
|
|
||||||
Text("\(summaryMang.ratio)")
|
|
||||||
.font(.nps(font: .bold, size: 24))
|
|
||||||
.foregroundStyle(summaryMang.ratio > 70 ? Color(.Other.blue):Color(.Other.red))
|
|
||||||
Text("%")
|
|
||||||
.font(.nps(font: .bold, size: 20))
|
|
||||||
.foregroundStyle(Color(.Text.detail))
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// ManagementView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/11/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ManagementView: View {
|
||||||
|
var body: some View {
|
||||||
|
Text("학습 관리")
|
||||||
|
}
|
||||||
|
}
|
14
AcaMate/1. View/12. Main/123. Chatting/ChattingView.swift
Normal file
14
AcaMate/1. View/12. Main/123. Chatting/ChattingView.swift
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// ChattingView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/11/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ChattingView: View {
|
||||||
|
var body: some View {
|
||||||
|
Text("채팅")
|
||||||
|
}
|
||||||
|
}
|
14
AcaMate/1. View/12. Main/124. Calendar/CalendarView.swift
Normal file
14
AcaMate/1. View/12. Main/124. Calendar/CalendarView.swift
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// CalendarView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/11/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct CalendarView: View {
|
||||||
|
var body: some View {
|
||||||
|
Text("일정")
|
||||||
|
}
|
||||||
|
}
|
15
AcaMate/1. View/12. Main/125. Etc/EtcView.swift
Normal file
15
AcaMate/1. View/12. Main/125. Etc/EtcView.swift
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// EtcView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/11/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct EtcView: View {
|
||||||
|
var body: some View {
|
||||||
|
Text("더보기")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ struct BottomView: View {
|
||||||
@State private var calendarID = UUID()
|
@State private var calendarID = UUID()
|
||||||
@State private var etcID = UUID()
|
@State private var etcID = UUID()
|
||||||
|
|
||||||
|
@Binding var menuName: MenuName
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let idList: [UUID] = [homeID,managementID,chattingID,calendarID,etcID]
|
let idList: [UUID] = [homeID,managementID,chattingID,calendarID,etcID]
|
||||||
|
|
||||||
|
@ -39,13 +40,14 @@ struct BottomView: View {
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
let idList: [UUID] = [homeID,managementID,chattingID,calendarID,etcID]
|
let idList: [UUID] = [homeID,managementID,chattingID,calendarID,etcID]
|
||||||
let btnText: [String] = ["홈", "학습 관리", "채팅", "일정", "더보기"]
|
//["홈", "학습 관리", "채팅", "일정", "더보기"]
|
||||||
|
let btnType: [MenuName] = [.Home, .Management, .Chatting, .Calendar, .Etc]
|
||||||
let btnImage: [Image] = [Image(.Icon.home),Image(.Icon.management),Image(.Icon.chatting),Image(.Icon.calendar),Image(.Icon.etc)]
|
let btnImage: [Image] = [Image(.Icon.home),Image(.Icon.management),Image(.Icon.chatting),Image(.Icon.calendar),Image(.Icon.etc)]
|
||||||
|
|
||||||
idList.enumerated().forEach { (index, id) in
|
idList.enumerated().forEach { (index, id) in
|
||||||
btnVM.btnStates[id] = ButtonState()
|
btnVM.btnStates[id] = ButtonState()
|
||||||
btnVM.setSize(for: id, newWidth: 52, newHeight: 52)
|
btnVM.setSize(for: id, newWidth: 52, newHeight: 52)
|
||||||
btnVM.setText(for: id, newText: btnText[index],
|
btnVM.setText(for: id, newText: btnType[index].rawValue,
|
||||||
newFont: .nps(font: .bold, size: 6))
|
newFont: .nps(font: .bold, size: 6))
|
||||||
btnVM.setImage(for: id, newImage: btnImage[index])
|
btnVM.setImage(for: id, newImage: btnImage[index])
|
||||||
|
|
||||||
|
@ -56,6 +58,7 @@ struct BottomView: View {
|
||||||
btnVM.setIsSelected(for: $0, newValue: false)
|
btnVM.setIsSelected(for: $0, newValue: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
menuName = btnType[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,69 +13,44 @@ struct MainView: View {
|
||||||
@State var cancellables: Set<AnyCancellable> = []
|
@State var cancellables: Set<AnyCancellable> = []
|
||||||
@Binding var naviState : NaviState
|
@Binding var naviState : NaviState
|
||||||
|
|
||||||
@State private var scrollOffset: CGPoint = .zero
|
@State var menuName: MenuName
|
||||||
@State private var topViewState: Bool = false
|
|
||||||
|
// @State private var scrollOffset: CGPoint = .zero
|
||||||
|
// @State private var topViewState: Bool = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
ZStack {
|
Group {
|
||||||
OffsetObservableScrollView(scrollOffset: $scrollOffset) { proxy in
|
switch menuName {
|
||||||
VStack(spacing: 0) {
|
case .Home:
|
||||||
TopProfileView()
|
HomeView()
|
||||||
.padding(EdgeInsets(top: 0, leading: 0, bottom: 12, trailing: 0))
|
case .Management:
|
||||||
AttendanceBoxView()
|
ManagementView()
|
||||||
.background {
|
case .Chatting:
|
||||||
RoundedRectangle(cornerRadius: 8)
|
ChattingView()
|
||||||
.foregroundStyle(Color(.Other.cell))
|
case .Calendar:
|
||||||
}
|
CalendarView()
|
||||||
.padding(EdgeInsets(top: 12, leading: 24, bottom: 12, trailing: 24))
|
case .Etc:
|
||||||
AttendanceBoxView()
|
EtcView()
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 8)
|
|
||||||
.foregroundStyle(Color(.Other.cell))
|
|
||||||
}
|
|
||||||
.padding(EdgeInsets(top: 12, leading: 24, bottom: 12, trailing: 24))
|
|
||||||
AttendanceBoxView()
|
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 8)
|
|
||||||
.foregroundStyle(Color(.Other.cell))
|
|
||||||
}
|
|
||||||
.padding(EdgeInsets(top: 12, leading: 24, bottom: 12, trailing: 24))
|
|
||||||
CalendarBoxView(summaryCalDataList: [
|
|
||||||
SummaryCalendar(id: "123", date: "2025-02-28", summary: "요약내용입니다."),
|
|
||||||
SummaryCalendar(id: "123", date: "2025-02-28", summary: "요약내용입니다.")])
|
|
||||||
|
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 8)
|
|
||||||
.foregroundStyle(Color(.Other.cell))
|
|
||||||
}
|
|
||||||
.padding(EdgeInsets(top: 12, leading: 24, bottom: 12, trailing: 24))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if topViewState {
|
|
||||||
VStack(spacing: 0) {
|
|
||||||
TopView(titleName: "Name")
|
|
||||||
.transition(.move(edge: .top))
|
|
||||||
.animation(.easeInOut, value: scrollOffset)
|
|
||||||
Spacer(minLength: 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BottomView()
|
Spacer(minLength: 1)
|
||||||
|
|
||||||
|
BottomView(menuName: $menuName)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.onChange(of: scrollOffset.y) { oldValue, newValue in
|
//
|
||||||
if newValue > 200 && topViewState == false {
|
// .onChange(of: scrollOffset.y) { oldValue, newValue in
|
||||||
topViewState = true
|
// if newValue > 200 && topViewState == false {
|
||||||
} else if newValue < 20 && topViewState == true{
|
// topViewState = true
|
||||||
topViewState = false
|
// } else if newValue < 20 && topViewState == true{
|
||||||
}
|
// topViewState = false
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ struct ButtonState {
|
||||||
var textColor: Color = .Text.detail
|
var textColor: Color = .Text.detail
|
||||||
var isUsable: Bool = true
|
var isUsable: Bool = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -- CircleBtn 전용 -- //
|
// -- CircleBtn 전용 -- //
|
||||||
|
|
||||||
var isSelected: Bool = false
|
var isSelected: Bool = false
|
||||||
|
|
|
@ -13,6 +13,8 @@ struct NaviState: Equatable {
|
||||||
var act: NaviAction
|
var act: NaviAction
|
||||||
var path: PathName
|
var path: PathName
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static func == (lhs: NaviState, rhs: NaviState) -> Bool {
|
static func == (lhs: NaviState, rhs: NaviState) -> Bool {
|
||||||
return lhs.act == rhs.act && lhs.path == rhs.path
|
return lhs.act == rhs.act && lhs.path == rhs.path
|
||||||
}
|
}
|
||||||
|
@ -21,6 +23,7 @@ struct NaviState: Equatable {
|
||||||
self.act = act
|
self.act = act
|
||||||
self.path = path
|
self.path = path
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NaviAction: Hashable {
|
enum NaviAction: Hashable {
|
||||||
|
@ -45,3 +48,11 @@ enum PathName: Hashable {
|
||||||
|
|
||||||
case NONE
|
case NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MenuName: String, Hashable {
|
||||||
|
case Home = "홈"
|
||||||
|
case Management = "학습 관리"
|
||||||
|
case Chatting = "채팅"
|
||||||
|
case Calendar = "일정"
|
||||||
|
case Etc = "더보기"
|
||||||
|
}
|
||||||
|
|
15
AcaMate/2. Model/Notice Data.swift
Normal file
15
AcaMate/2. Model/Notice Data.swift
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// Notice Data.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/11/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct SummaryNotice {
|
||||||
|
var id: String
|
||||||
|
var title: String
|
||||||
|
var date: String
|
||||||
|
var new: Bool
|
||||||
|
}
|
|
@ -10,7 +10,6 @@ import Combine
|
||||||
|
|
||||||
class AppViewModel: ObservableObject {
|
class AppViewModel: ObservableObject {
|
||||||
@Published var isLoading: Bool = false
|
@Published var isLoading: Bool = false
|
||||||
|
|
||||||
@Published var showAlert: Bool = false
|
@Published var showAlert: Bool = false
|
||||||
|
|
||||||
var alertData: AlertData = .init(body: "")
|
var alertData: AlertData = .init(body: "")
|
||||||
|
|
|
@ -60,6 +60,13 @@ class ButtonViewModel: ObservableObject {
|
||||||
btnStates[id] = state
|
btnStates[id] = state
|
||||||
objectWillChange.send()
|
objectWillChange.send()
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// func setDisable(for id: UUID, _ newValue: Bool) {
|
||||||
|
// var state = btnStates[id] ?? ButtonState()
|
||||||
|
// state.isUsable = newValue
|
||||||
|
// btnStates[id] = state
|
||||||
|
// objectWillChange.send()
|
||||||
|
// }
|
||||||
|
|
||||||
// -- CircleBtn 전용 -- //
|
// -- CircleBtn 전용 -- //
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user