main #10
|
@ -324,7 +324,7 @@
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited) DEV";
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited) DEV LOCAL";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
// MARK: - ACAMATE
|
// MARK: - ACAMATE
|
||||||
// APPSTORE_URL : https://apps.apple.com/us/app/%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8%EB%A9%94%EC%9D%B4%ED%8A%B8/id6739448113
|
// APPSTORE_URL : https://apps.apple.com/us/app/%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8%EB%A9%94%EC%9D%B4%ED%8A%B8/id6739448113
|
||||||
#if DEV && LOCAL
|
//#if DEV && LOCAL
|
||||||
public let API_URL: String = "http://localhost:5144"
|
//public let API_URL: String = "http://localhost:5144"
|
||||||
#elseif DEV
|
//#else
|
||||||
|
#if DEV
|
||||||
public let API_URL: String = "https://devacamate.ipstein.myds.me"
|
public let API_URL: String = "https://devacamate.ipstein.myds.me"
|
||||||
#else
|
#else
|
||||||
public let API_URL: String = "https://acamate.ipstein.myds.me"
|
public let API_URL: String = "https://acamate.ipstein.myds.me"
|
||||||
|
|
|
@ -15,10 +15,18 @@ struct CircleBtnView: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let state = vm.btnStates[id] {
|
if let state = vm.btnStates[id] {
|
||||||
Button{
|
ZStack {
|
||||||
guard let action = state.action else {return}
|
if state.isReverse {
|
||||||
action()
|
Circle()
|
||||||
} label: {
|
.foregroundStyle(state.backColor)
|
||||||
|
.frame(width: state.width, height: state.height)
|
||||||
|
.innerShadow(shape: Circle(), color: Color(.Text.black).opacity(0.75), blur: 8, x: 0, y: 4)
|
||||||
|
} else {
|
||||||
|
Circle()
|
||||||
|
.foregroundStyle(state.backColor)
|
||||||
|
.frame(width: state.width, height: state.height)
|
||||||
|
.shadow(color: Color(.Text.black).opacity(0.75), radius: 8, x: 4, y: 8)
|
||||||
|
}
|
||||||
VStack(alignment: .center, spacing: 0) {
|
VStack(alignment: .center, spacing: 0) {
|
||||||
if let image = state.image {
|
if let image = state.image {
|
||||||
image
|
image
|
||||||
|
@ -27,31 +35,21 @@ struct CircleBtnView: View {
|
||||||
.foregroundStyle(state.foreColor)
|
.foregroundStyle(state.foreColor)
|
||||||
.frame(width: state.width/2, height: state.height/2)
|
.frame(width: state.width/2, height: state.height/2)
|
||||||
}
|
}
|
||||||
//
|
|
||||||
if let title = state.title, let font = state.font {
|
if let title = state.title, let font = state.font {
|
||||||
Text("\(title)")
|
Text("\(title)")
|
||||||
.font(font)
|
.font(font)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.minimumScaleFactor(0.5)
|
.minimumScaleFactor(0.5)
|
||||||
.truncationMode(.tail)
|
.truncationMode(.tail)
|
||||||
.foregroundStyle(state.textColor)
|
.foregroundStyle(state.foreColor)
|
||||||
// .padding()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.background {
|
|
||||||
if state.isReverse {
|
|
||||||
Circle()
|
|
||||||
.accentColor(state.backColor)
|
|
||||||
.frame(width: state.width, height: state.height)
|
|
||||||
.innerShadow(shape: Circle(), color: Color(.Text.black).opacity(0.75), blur: 8, x: 0, y: 4)
|
|
||||||
} else {
|
|
||||||
Circle()
|
|
||||||
.accentColor(state.backColor)
|
|
||||||
.frame(width: state.width, height: state.height)
|
|
||||||
.shadow(color: Color(.Text.black).opacity(0.75), radius: 8, x: 4, y: 8)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(width: state.width, height: state.height)
|
||||||
|
.onTapGesture {
|
||||||
|
guard let action = state.action else {return}
|
||||||
|
action()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,6 +20,7 @@ struct SimpleBtnView: View {
|
||||||
.font(font)
|
.font(font)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.minimumScaleFactor(0.5)
|
.minimumScaleFactor(0.5)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
.truncationMode(.tail)
|
.truncationMode(.tail)
|
||||||
.foregroundStyle(state.textColor)
|
.foregroundStyle(state.textColor)
|
||||||
.frame(width: state.width, height: state.height)
|
.frame(width: state.width, height: state.height)
|
||||||
|
@ -38,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()
|
||||||
}
|
}
|
||||||
|
|
71
AcaMate/1. View/10. Common/OffsetObservableScollView.swift
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
//
|
||||||
|
// OffsetObservableScollView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/10/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
struct OffsetObservableScrollView<Content: View>: View {
|
||||||
|
var axes: Axis.Set = .vertical
|
||||||
|
var showsIndicators: Bool = true
|
||||||
|
|
||||||
|
@Binding var scrollOffset: CGPoint
|
||||||
|
@ViewBuilder var content: (ScrollViewProxy) -> Content
|
||||||
|
|
||||||
|
@Namespace var coordinateSpaceName: Namespace.ID
|
||||||
|
|
||||||
|
init(
|
||||||
|
_ axes: Axis.Set = .vertical,
|
||||||
|
showsIndicators: Bool = true,
|
||||||
|
scrollOffset: Binding<CGPoint>,
|
||||||
|
@ViewBuilder content: @escaping (ScrollViewProxy) -> Content
|
||||||
|
) {
|
||||||
|
self.axes = axes
|
||||||
|
self.showsIndicators = showsIndicators
|
||||||
|
self._scrollOffset = scrollOffset
|
||||||
|
self.content = content
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView(axes, showsIndicators: showsIndicators) {
|
||||||
|
ScrollViewReader { scrollViewProxy in
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
// 맨 위로 스크롤하기 위한 anchor 뷰 (id "TOP")
|
||||||
|
Color.clear
|
||||||
|
.frame(height: 1)
|
||||||
|
.id("TOP")
|
||||||
|
content(scrollViewProxy)
|
||||||
|
.overlay {
|
||||||
|
GeometryReader { geometryProxy in
|
||||||
|
Color.clear
|
||||||
|
.preference(
|
||||||
|
key: ScrollOffsetPreferenceKey.self,
|
||||||
|
value: CGPoint (
|
||||||
|
x: -geometryProxy.frame(in: .named(coordinateSpaceName)).minX,
|
||||||
|
y: -geometryProxy.frame(in: .named(coordinateSpaceName)).minY
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.coordinateSpace(name: coordinateSpaceName)
|
||||||
|
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
|
||||||
|
// printLog("\(scrollOffset) -> \(value)")
|
||||||
|
scrollOffset = value
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScrollOffsetPreferenceKey: PreferenceKey {
|
||||||
|
static var defaultValue: CGPoint = .zero
|
||||||
|
|
||||||
|
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
|
||||||
|
value = nextValue()
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,9 @@ struct IntroView: View {
|
||||||
|
|
||||||
.onAppear {
|
.onAppear {
|
||||||
printLog("IntroView_onAppear")
|
printLog("IntroView_onAppear")
|
||||||
|
#if LOCAL
|
||||||
|
naviState.set(act: .RESET, path: .Login)
|
||||||
|
#else
|
||||||
subscribeAlertAction()
|
subscribeAlertAction()
|
||||||
loadVersion()
|
loadVersion()
|
||||||
.sink { completion in
|
.sink { completion in
|
||||||
|
@ -66,7 +69,7 @@ struct IntroView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
86
AcaMate/1. View/12. Main/121. Home/AttendanceBoxView.swift
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
//
|
||||||
|
// AttendanceView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/7/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct AttendanceBoxView: View {
|
||||||
|
@State var monthlyGroup: (Int,Int) = (5,10)//(0,0)
|
||||||
|
@State var dailyGroup: (Int,Int) = (3,4)//(0,0)
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
DashBoardView(image: Image(.Icon.attendance),
|
||||||
|
title: "출석")
|
||||||
|
{
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
AttCellView(isDaily: false, valueGroup: $monthlyGroup)
|
||||||
|
Spacer()
|
||||||
|
AttCellView(isDaily: true, valueGroup: $dailyGroup)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
} moreAction: {
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 출석 쪽 더보기 동작 만들기
|
||||||
|
print("123")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AttCellView: View {
|
||||||
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
|
@State private var cellBtnID = UUID()
|
||||||
|
let isDaily: Bool
|
||||||
|
|
||||||
|
@Binding var valueGroup: (Int,Int)
|
||||||
|
@State private var cellText: (name: String, group: String) = ("","")
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
CircleBtnView(vm: btnVM, id: cellBtnID)
|
||||||
|
VStack(alignment: .leading,spacing: 0) {
|
||||||
|
HStack(alignment: .center, spacing: 2) {
|
||||||
|
Text("\(cellText.name)").font(.nps(font: .bold, size: 12))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Text("출석").font(.nps(size: 12))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
}
|
||||||
|
.padding(.top,4)
|
||||||
|
HStack(alignment: .center, spacing: 2) {
|
||||||
|
Spacer()
|
||||||
|
Text("\(valueGroup.0)").font(.nps(font: .bold, size: 20))
|
||||||
|
.foregroundStyle(((Double(valueGroup.0)/Double(valueGroup.1)) < 0.7) ? Color(.Other.red) : Color(.Other.blue))
|
||||||
|
.frame(width: 28,alignment: .center)
|
||||||
|
Text("/").font(.nps(size: 12))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Text("\(valueGroup.1)").font(.nps(font: .bold, size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
.frame(width: 28,alignment: .center)
|
||||||
|
Text("\(cellText.group)")
|
||||||
|
.font(.nps(size: 16))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
.truncationMode(.tail)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
btnVM.setImage(for: cellBtnID,
|
||||||
|
newImage: isDaily ? Image(.Icon.attendanceDaily) : Image(.Icon.attendanceMonthly))
|
||||||
|
btnVM.setSize(for: cellBtnID, newWidth: 48, newHeight: 48)
|
||||||
|
btnVM.setIsReverse(for: cellBtnID, newValue: true)
|
||||||
|
btnVM.setIsSelected(for: cellBtnID, newValue: true)
|
||||||
|
|
||||||
|
if isDaily {
|
||||||
|
cellText = ("일일", "시간")
|
||||||
|
} else {
|
||||||
|
cellText = ("월간", "일")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
AcaMate/1. View/12. Main/121. Home/CalendarBoxView.swift
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
//
|
||||||
|
// CalendarBoxView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/10/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct CalendarBoxView: View {
|
||||||
|
@State var summaryCalDataList: [SummaryCalendar]
|
||||||
|
var body: some View {
|
||||||
|
|
||||||
|
DashBoardView(image: Image(.Icon.calendar), title: "최근 일정") {
|
||||||
|
if !summaryCalDataList.isEmpty {
|
||||||
|
VStack(spacing: 12) {
|
||||||
|
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: {
|
||||||
|
printLog("최근일정의 더보기")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CalCellView: View {
|
||||||
|
var summaryCalData: SummaryCalendar
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 8) {
|
||||||
|
HStack (spacing: 12) {
|
||||||
|
Image(.Icon.clock)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 24, height: 24, alignment: .center)
|
||||||
|
Text("\(summaryCalData.date)")
|
||||||
|
.font(.nps(size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
}
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
Text("\(summaryCalData.summary)")
|
||||||
|
.font(.nps(size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.black))
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
.truncationMode(.tail)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.padding(12)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
.stroke(Color(.Second.normal), lineWidth: 2)
|
||||||
|
.fill(Color(.Second.light))
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
printLog("캘린더 내부 셀 클릭")
|
||||||
|
// MARK: TO-DO
|
||||||
|
// Summary의 날짜 위치로 이동하게 하는걸로
|
||||||
|
// SummaryCalendar' id 를 이용하는걸로
|
||||||
|
// 해당 날짜의 해당 이벤트가 아니라 그냥 해당 날짜로 이동하는게 좋을 것으로 보임
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
53
AcaMate/1. View/12. Main/121. Home/DashBoardView.swift
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// DashBoardView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/10/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct DashBoardView<Content: View>: View {
|
||||||
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
|
@State private var attMoreBtnID = UUID()
|
||||||
|
let image: Image
|
||||||
|
let title: String
|
||||||
|
@ViewBuilder let content: Content
|
||||||
|
var moreAction: VOID_TO_VOID?
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
HStack(spacing: 0){
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 24, height: 24, alignment: .center)
|
||||||
|
.padding([.trailing],4)
|
||||||
|
Text("\(title)")
|
||||||
|
.font(.nps(font: .bold, size: 20))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
Spacer()
|
||||||
|
SimpleBtnView(vm: btnVM, id: attMoreBtnID)
|
||||||
|
}
|
||||||
|
.padding([.bottom],2)
|
||||||
|
|
||||||
|
Rectangle()
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: 2)
|
||||||
|
.foregroundStyle(Color(.Second.normal))
|
||||||
|
.padding([.bottom],12)
|
||||||
|
|
||||||
|
content
|
||||||
|
}
|
||||||
|
.padding(24)
|
||||||
|
.onAppear {
|
||||||
|
btnVM.setSize(for: attMoreBtnID, newWidth: 40, newHeight: 24)
|
||||||
|
btnVM.setText(for: attMoreBtnID, newText: "더보기", newFont: .nps(size: 12))
|
||||||
|
btnVM.setTextColor(for: attMoreBtnID, newColor: .Text.disabled)
|
||||||
|
|
||||||
|
if let action = moreAction {
|
||||||
|
btnVM.setAction(for: attMoreBtnID, newAction: action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
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
|
@ -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
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
136
AcaMate/1. View/12. Main/121. Home/TopProfileView.swift
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
//
|
||||||
|
// TopProfileView.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/5/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct TopProfileView: View {
|
||||||
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
|
|
||||||
|
var userType: UserType
|
||||||
|
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 여기서 이름 떙겨오는것도 고민을 해야 함
|
||||||
|
var childrenList: [String] = ["name1", "name2", "name3"]
|
||||||
|
|
||||||
|
var academyName: String = "Academy' NAME"
|
||||||
|
var myName: String = "Name"
|
||||||
|
|
||||||
|
@State private var typeName: String = "유형"
|
||||||
|
@State private var ParentsSelectID: UUID?
|
||||||
|
|
||||||
|
@State private var shopID = UUID()
|
||||||
|
@State private var notifyID = UUID()
|
||||||
|
@State private var childIDList: [UUID] = []
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 0){
|
||||||
|
VStack(alignment: .center, spacing: 0) {
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
SimpleBtnView(vm: btnVM, id: shopID)
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
SimpleBtnView(vm: btnVM, id: notifyID)
|
||||||
|
} /// 최상단 버튼 Stack
|
||||||
|
ZStack{
|
||||||
|
Circle()
|
||||||
|
.stroke(Color(.Second.normal) ,lineWidth: 4)
|
||||||
|
.frame(width: 200, height: 200)
|
||||||
|
|
||||||
|
Text("\(typeName)")
|
||||||
|
.font(.nps(font: .bold, size: 48))
|
||||||
|
.foregroundStyle(Color(.Second.normal))
|
||||||
|
|
||||||
|
|
||||||
|
} /// 중앙 원형 Stack
|
||||||
|
.padding([.top, .bottom], 40)
|
||||||
|
VStack(alignment: .center, spacing: 8) {
|
||||||
|
Text("\(self.academyName)")
|
||||||
|
.frame(alignment: .center)
|
||||||
|
.font(.nps(font: .bold, size: 36))
|
||||||
|
.foregroundStyle(Color(.Text.title))
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
.truncationMode(.tail)
|
||||||
|
Text("\(self.myName)")
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.frame(alignment: .center)
|
||||||
|
.font(.nps(size: 18))
|
||||||
|
.foregroundStyle(Color(.Text.detail))
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
.truncationMode(.tail)
|
||||||
|
}
|
||||||
|
} /// 위쪽 VStack
|
||||||
|
.padding(EdgeInsets(top: 24, leading: 24, bottom: 12, trailing: 24))
|
||||||
|
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 여기에 가로스크롤 넣어야 할거 같음
|
||||||
|
if userType == .Parent {
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
ForEach(Array(childIDList.enumerated()),id: \.offset){ index, id in
|
||||||
|
CircleBtnView(vm: btnVM, id: id)
|
||||||
|
if index != childIDList.count-1 {
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /// 아래쪽 HStack
|
||||||
|
.padding([.leading, .trailing, .bottom], 24)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fullDrawView(.Other.cell)
|
||||||
|
|
||||||
|
|
||||||
|
.onAppear {
|
||||||
|
let topBtnIDList = [shopID,notifyID]
|
||||||
|
let iconList = [Image(.Icon.market), Image(.Icon.notificationSET)]
|
||||||
|
|
||||||
|
topBtnIDList.enumerated().forEach { (index, id) in
|
||||||
|
btnVM.setImage(for: topBtnIDList[index], newImage: iconList[index])
|
||||||
|
btnVM.setSize(for: topBtnIDList[index], newWidth: 40, newHeight: 40)
|
||||||
|
}
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 마켓 버튼과 알림 버튼 동작 로직 구현하기
|
||||||
|
|
||||||
|
|
||||||
|
switch self.userType {
|
||||||
|
case .Student:
|
||||||
|
typeName = "학생"
|
||||||
|
case .Parent:
|
||||||
|
typeName = "학부모"
|
||||||
|
for _ in 0..<childrenList.count {
|
||||||
|
childIDList.append(UUID())
|
||||||
|
}
|
||||||
|
ParentsSelectID = childIDList[0]
|
||||||
|
btnVM.setIsSelected(for: childIDList[0], newValue: true)
|
||||||
|
|
||||||
|
childIDList.enumerated().forEach { (index, id) in
|
||||||
|
btnVM.setImage(for: id, newImage: Image(.Icon.face))
|
||||||
|
btnVM.setSize(for: id, newWidth: 64, newHeight: 64)
|
||||||
|
btnVM.setText(for: id, newText: "\(childrenList[index])", newFont: .nps(size: 12))
|
||||||
|
// MARK: TO-DO
|
||||||
|
// 좀더 자세한 동작 로직 구현 필요
|
||||||
|
btnVM.setAction(for: id) {
|
||||||
|
if let selectID = ParentsSelectID {
|
||||||
|
btnVM.setIsSelected(for: selectID, newValue: false)
|
||||||
|
}
|
||||||
|
btnVM.setIsSelected(for: id, newValue: true)
|
||||||
|
ParentsSelectID = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case .Teacher:
|
||||||
|
typeName = "선생님"
|
||||||
|
case .Admin:
|
||||||
|
typeName = "관리자"
|
||||||
|
case .Employee:
|
||||||
|
typeName = "직원"
|
||||||
|
case .ETC:
|
||||||
|
typeName = "방문객"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
//
|
|
||||||
// TopProfileView.swift
|
|
||||||
// AcaMate
|
|
||||||
//
|
|
||||||
// Created by TAnine on 2/5/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct TopProfileView: View {
|
|
||||||
var userType: UserType = .ETC
|
|
||||||
var childrenList: [String] = ["name1", "name2", "name3"]
|
|
||||||
var academyName: String = "Academy' NAME"
|
|
||||||
var myName: String = "Name"
|
|
||||||
|
|
||||||
@State var childNum: Int = 0
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VStack(spacing: 0){
|
|
||||||
VStack(alignment: .center, spacing: 0) {
|
|
||||||
HStack(spacing: 0) {
|
|
||||||
// SimpleBtnView(image: Image(.Icon.market), title: nil, font: nil,
|
|
||||||
// width: 40, height: 40)
|
|
||||||
// .doAction {
|
|
||||||
// printLog("TEST")
|
|
||||||
// }
|
|
||||||
Spacer(minLength: 1)
|
|
||||||
// SimpleBtnView(image: Image(.Icon.notificationSET), title: nil, font: nil,
|
|
||||||
// width: 40, height: 40)
|
|
||||||
// .doAction {
|
|
||||||
// printLog("TEST")
|
|
||||||
// }
|
|
||||||
} /// 최상단 버튼 Stack
|
|
||||||
ZStack{
|
|
||||||
Circle()
|
|
||||||
.stroke(Color(.Second.normal) ,lineWidth: 4)
|
|
||||||
.frame(width: 200, height: 200)
|
|
||||||
switch self.userType {
|
|
||||||
case .Student:
|
|
||||||
// MARK: TO-DO
|
|
||||||
// 학생일때 표시하는거 어떻게 할 건지 좀 더 고민을 해보자
|
|
||||||
Image(.Icon.face)
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 150, height: 150)
|
|
||||||
case .Parent:
|
|
||||||
Text("학부모")
|
|
||||||
.font(.nps(font: .bold, size: 48))
|
|
||||||
.foregroundStyle(Color(.Second.normal))
|
|
||||||
case .Teacher:
|
|
||||||
Text("선생님")
|
|
||||||
.font(.nps(font: .bold, size: 48))
|
|
||||||
.foregroundStyle(Color(.Second.normal))
|
|
||||||
case .Admin:
|
|
||||||
Text("관리자")
|
|
||||||
.font(.nps(font: .bold, size: 48))
|
|
||||||
.foregroundStyle(Color(.Second.normal))
|
|
||||||
case .Employee:
|
|
||||||
Text("직원")
|
|
||||||
.font(.nps(font: .bold, size: 48))
|
|
||||||
.foregroundStyle(Color(.Second.normal))
|
|
||||||
case .ETC:
|
|
||||||
Text("방문객")
|
|
||||||
.font(.nps(font: .bold, size: 48))
|
|
||||||
.foregroundStyle(Color(.Second.normal))
|
|
||||||
}
|
|
||||||
} /// 중앙 원형 Stack
|
|
||||||
.padding([.top, .bottom], 40)
|
|
||||||
VStack(alignment: .center, spacing: 8) {
|
|
||||||
Text("\(self.academyName)")
|
|
||||||
.frame(alignment: .center)
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.font(.nps(font: .bold, size: 36))
|
|
||||||
Text("\(self.myName)")
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.frame(alignment: .center)
|
|
||||||
.font(.nps(size: 18))
|
|
||||||
.foregroundStyle(Color(.Text.detail))
|
|
||||||
}
|
|
||||||
} /// 위쪽 VStack
|
|
||||||
.padding(EdgeInsets(top: 24, leading: 24, bottom: 12, trailing: 24))
|
|
||||||
|
|
||||||
HStack(spacing: 0) {
|
|
||||||
// ForEach(Array(childrenList.enumerated()),id: \.offset){ index, name in
|
|
||||||
// CircleBtnView(title: "\(name)", image: Image(.Icon.face),
|
|
||||||
// // MARK: TO-DO
|
|
||||||
// /// 이 바인딩 이거 잘 작동 되는지 후에 확인 할것
|
|
||||||
// isSelected: Binding(
|
|
||||||
// get: { self.childNum == index },
|
|
||||||
// set: { _ in self.childNum = index }
|
|
||||||
// ), isReverse: false) {
|
|
||||||
// self.childNum = index
|
|
||||||
// }
|
|
||||||
// if index != childrenList.count-1 {
|
|
||||||
// Spacer()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
} /// 아래쪽 HStack
|
|
||||||
.padding([.leading, .trailing], 24)
|
|
||||||
}
|
|
||||||
.fullDrawView(.Other.cell)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#Preview {
|
|
||||||
TopProfileView()
|
|
||||||
}
|
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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]
|
||||||
|
|
||||||
|
@ -29,11 +30,7 @@ struct BottomView: View {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// MARK: TO-DO
|
.padding(EdgeInsets(top: 12, leading: 24, bottom: 0, trailing: 24))
|
||||||
// 이거 패딩 제대로 안먹는거 이유 찾기
|
|
||||||
.padding([.top],12)
|
|
||||||
.padding([.horizontal],24)
|
|
||||||
// .padding(EdgeInsets(top: 12, leading: 24, bottom: 0, trailing: 24))
|
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
|
@ -43,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: 48, newHeight: 48)
|
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])
|
||||||
|
|
||||||
|
@ -60,6 +58,7 @@ struct BottomView: View {
|
||||||
btnVM.setIsSelected(for: $0, newValue: false)
|
btnVM.setIsSelected(for: $0, newValue: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
menuName = btnType[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,22 +13,44 @@ struct MainView: View {
|
||||||
@State var cancellables: Set<AnyCancellable> = []
|
@State var cancellables: Set<AnyCancellable> = []
|
||||||
@Binding var naviState : NaviState
|
@Binding var naviState : NaviState
|
||||||
|
|
||||||
|
@State var menuName: MenuName
|
||||||
|
|
||||||
|
// @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) {
|
||||||
TopView(titleName: "Name")
|
Group {
|
||||||
|
switch menuName {
|
||||||
|
case .Home:
|
||||||
|
HomeView()
|
||||||
|
case .Management:
|
||||||
|
ManagementView()
|
||||||
|
case .Chatting:
|
||||||
|
ChattingView()
|
||||||
|
case .Calendar:
|
||||||
|
CalendarView()
|
||||||
|
case .Etc:
|
||||||
|
EtcView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(minLength: 1)
|
||||||
|
|
||||||
Spacer()
|
BottomView(menuName: $menuName)
|
||||||
|
|
||||||
BottomView()
|
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
|
|
||||||
// .backgroundStyle(Color(.Normal.dark))
|
|
||||||
// .safeAreaInset(edge: .bottom, spacing: 0) {
|
|
||||||
// Color(.Normal.dark)
|
|
||||||
//// .frame(height: 0)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
// .fullDrawView(Color(.Normal.dark))
|
.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
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,12 @@ struct TopView: View {
|
||||||
@StateObject var btnVM = ButtonViewModel()
|
@StateObject var btnVM = ButtonViewModel()
|
||||||
|
|
||||||
@State var titleName: String = ""
|
@State var titleName: String = ""
|
||||||
@State var changeLogo: Bool = false
|
|
||||||
@State var tailLogo: Bool = false
|
|
||||||
|
|
||||||
@State private var leftBtnID = UUID()
|
@State private var leftBtnID = UUID()
|
||||||
@State private var rightBtnID = UUID()
|
@State private var rightBtnID = UUID()
|
||||||
|
|
||||||
var myType: UserType = .Teacher
|
//MARK: - 변경 값
|
||||||
|
var myType: UserType = .Student
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(alignment: .center, spacing: 0) {
|
HStack(alignment: .center, spacing: 0) {
|
||||||
|
@ -36,6 +35,7 @@ struct TopView: View {
|
||||||
.foregroundStyle(Color(.Text.detail))
|
.foregroundStyle(Color(.Text.detail))
|
||||||
.font(.nps(font: .bold, size: 20))
|
.font(.nps(font: .bold, size: 20))
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
SimpleBtnView(vm: btnVM, id: rightBtnID)
|
SimpleBtnView(vm: btnVM, id: rightBtnID)
|
||||||
.padding(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 24))
|
.padding(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 24))
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
14
AcaMate/2. Model/Calendar Data.swift
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
// SimpleCalendar.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/10/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct SummaryCalendar {
|
||||||
|
var id: String
|
||||||
|
var date: String
|
||||||
|
var summary: String
|
||||||
|
}
|
16
AcaMate/2. Model/Management Data.swift
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// ManagementData.swift
|
||||||
|
// AcaMate
|
||||||
|
//
|
||||||
|
// Created by TAnine on 2/10/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct SummaryManagement {
|
||||||
|
var id: String
|
||||||
|
var title: String
|
||||||
|
var teacher: String
|
||||||
|
var ratio: Int
|
||||||
|
var homework: Int
|
||||||
|
}
|
|
@ -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
|
@ -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 전용 -- //
|
||||||
|
|
||||||
|
@ -74,7 +81,11 @@ class ButtonViewModel: ObservableObject {
|
||||||
func setIsReverse(for id: UUID, newValue: Bool){
|
func setIsReverse(for id: UUID, newValue: Bool){
|
||||||
var state = btnStates[id] ?? ButtonState()
|
var state = btnStates[id] ?? ButtonState()
|
||||||
state.isReverse = newValue
|
state.isReverse = newValue
|
||||||
state.backColor = newValue ? Color(.Second.light) : Color(.Normal.normal)
|
if state.isReverse {
|
||||||
|
state.backColor = Color(.Second.light)
|
||||||
|
} else {
|
||||||
|
state.backColor = Color(.Normal.normal)
|
||||||
|
}
|
||||||
btnStates[id] = state
|
btnStates[id] = state
|
||||||
objectWillChange.send()
|
objectWillChange.send()
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,42 @@ struct LoadingModifier: ViewModifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PressEffect: ViewModifier {
|
||||||
|
@State private var isPressed = false
|
||||||
|
var scale: CGFloat
|
||||||
|
var opacity: CGFloat
|
||||||
|
var duration: Double
|
||||||
|
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
content
|
||||||
|
.scaleEffect(isPressed ? scale : 1.0)
|
||||||
|
.opacity(isPressed ? opacity : 1.0)
|
||||||
|
.animation(.easeOut(duration: duration), value: isPressed)
|
||||||
|
.simultaneousGesture(
|
||||||
|
LongPressGesture(minimumDuration: 0.01)
|
||||||
|
.onChanged { _ in isPressed = true }
|
||||||
|
.onEnded { _ in isPressed = false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct PressBackgroundEffect: ViewModifier {
|
||||||
|
@State private var isPressed = false
|
||||||
|
var backgroundColor: Color
|
||||||
|
var duration: Double
|
||||||
|
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
content
|
||||||
|
.background(isPressed ? backgroundColor : Color.clear)
|
||||||
|
.animation(.easeOut(duration: duration), value: isPressed)
|
||||||
|
.simultaneousGesture(
|
||||||
|
LongPressGesture(minimumDuration: 0.01)
|
||||||
|
.onChanged { _ in isPressed = true }
|
||||||
|
.onEnded { _ in isPressed = false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extension View {
|
extension View {
|
||||||
/// View에 전체적으로 색 입히기
|
/// View에 전체적으로 색 입히기
|
||||||
func fullDrawView(_ backColor: Color) -> some View {
|
func fullDrawView(_ backColor: Color) -> some View {
|
||||||
|
@ -104,16 +140,14 @@ extension View {
|
||||||
.mask(shape.fill(LinearGradient(gradient: Gradient(colors: [.black, .clear]), startPoint: .topLeading, endPoint: .bottomTrailing)))
|
.mask(shape.fill(LinearGradient(gradient: Gradient(colors: [.black, .clear]), startPoint: .topLeading, endPoint: .bottomTrailing)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
func pressAnimation(scale: CGFloat = 0.95, opacity: CGFloat = 0.85, duration: Double = 0.1) -> some View {
|
||||||
func switchButtonStyle(_ animate: Bool) -> some View {
|
self.modifier(PressEffect(scale: scale, opacity: opacity, duration: duration))
|
||||||
if animate {
|
|
||||||
self.buttonStyle(DefaultButtonStyle())
|
}
|
||||||
} else {
|
}
|
||||||
self.buttonStyle(PlainButtonStyle())
|
extension View {
|
||||||
// .allowsHitTesting(false)
|
func pressColorAnimation(backgroundColor: Color = Color.black.opacity(0.1), duration: Double = 0.1) -> some View {
|
||||||
}
|
self.modifier(PressBackgroundEffect(backgroundColor: backgroundColor, duration: duration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//extension BUtton
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.114",
|
||||||
|
"green" : "0.114",
|
||||||
|
"red" : "0.114"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Attendance.imageset/Attendance.png
vendored
Normal file
After Width: | Height: | Size: 741 B |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Attendance.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Attendance.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 779 B |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Attendance_Daily.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Attendance_Daily.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 630 B |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Attendance_Monthly.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Attendance_Monthly.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Clock.imageset/Clock.png
vendored
Normal file
After Width: | Height: | Size: 1.8 KiB |
15
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Clock.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Clock.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"preserves-vector-representation" : true
|
||||||
|
}
|
||||||
|
}
|
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Drive OFF.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Drive OFF.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Drive OFF.imageset/Drive OFF.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Drive ON.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Drive ON.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Drive ON.imageset/Drive ON.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Drive.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Drive.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Drive.imageset/Drive.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
15
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Edu.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Edu.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"preserves-vector-representation" : true
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Edu.imageset/Edu.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Flag.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Flag.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Flag.imageset/Flag.png
vendored
Normal file
After Width: | Height: | Size: 463 B |
15
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Left.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Left.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"preserves-vector-representation" : true
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Left.imageset/Left.png
vendored
Normal file
After Width: | Height: | Size: 505 B |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Notice.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Notice.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Notice.imageset/Notice.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Notice_New.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Notice_New.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Notice_New.imageset/Notice_New.png
vendored
Normal file
After Width: | Height: | Size: 618 B |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Notice_Old.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Notice_Old.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Notice_Old.imageset/Notice_Old.png
vendored
Normal file
After Width: | Height: | Size: 579 B |
12
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Ratio.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Ratio.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Ratio.imageset/Ratio.png
vendored
Normal file
After Width: | Height: | Size: 1.8 KiB |
15
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Right.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Right.png",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"preserves-vector-representation" : true
|
||||||
|
}
|
||||||
|
}
|
BIN
AcaMate/6. Resources/Assets.xcassets/Image Folder/Icon/Right.imageset/Right.png
vendored
Normal file
After Width: | Height: | Size: 470 B |
BIN
AcaMate/6. Resources/Images/Icon/Attendance.png
Normal file
After Width: | Height: | Size: 741 B |
BIN
AcaMate/6. Resources/Images/Icon/Attendance_Daily.png
Normal file
After Width: | Height: | Size: 779 B |
BIN
AcaMate/6. Resources/Images/Icon/Attendance_Monthly.png
Normal file
After Width: | Height: | Size: 630 B |
Before Width: | Height: | Size: 636 B After Width: | Height: | Size: 636 B |
Before Width: | Height: | Size: 543 B After Width: | Height: | Size: 543 B |
BIN
AcaMate/6. Resources/Images/Icon/Clock.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
AcaMate/6. Resources/Images/Icon/Drive OFF.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
AcaMate/6. Resources/Images/Icon/Drive ON.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
AcaMate/6. Resources/Images/Icon/Drive.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
AcaMate/6. Resources/Images/Icon/Edu.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 635 B |
BIN
AcaMate/6. Resources/Images/Icon/Flag.png
Normal file
After Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 604 B After Width: | Height: | Size: 604 B |
BIN
AcaMate/6. Resources/Images/Icon/Left.png
Normal file
After Width: | Height: | Size: 505 B |
Before Width: | Height: | Size: 577 B After Width: | Height: | Size: 577 B |
BIN
AcaMate/6. Resources/Images/Icon/Notice.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
AcaMate/6. Resources/Images/Icon/Notice_New.png
Normal file
After Width: | Height: | Size: 618 B |
BIN
AcaMate/6. Resources/Images/Icon/Notice_Old.png
Normal file
After Width: | Height: | Size: 579 B |
BIN
AcaMate/6. Resources/Images/Icon/Ratio.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
AcaMate/6. Resources/Images/Icon/Right.png
Normal file
After Width: | Height: | Size: 470 B |
10
README.md
|
@ -11,3 +11,13 @@
|
||||||
2. kakao Login
|
2. kakao Login
|
||||||
3. naver Map
|
3. naver Map
|
||||||
4. firebase
|
4. firebase
|
||||||
|
|
||||||
|
## Git Commit message
|
||||||
|
1. [📝]: DOCS -> 문서 추가, 문서 수정 등
|
||||||
|
2. [✨]: FEAT -> 새로운 기능의 추가
|
||||||
|
3. [🔥]: FIRE -> 코드나 문서 등의 삭제
|
||||||
|
4. [🐛]: FIX BUG -> 버그 수정
|
||||||
|
5. [👷]: STYLE -> 직접적인 코드의 수정은 없는 경우 (빈줄 처리, 주석 등)
|
||||||
|
6. [♻️]: REFACTOR -> 코드 리팩토링
|
||||||
|
7. [✅]: TEST -> 테스트 코드 추가
|
||||||
|
8. [📁]: CHORE: 빌드 업무, 패키지 매니저 수정 등 (.gitignore 수정 등)
|
||||||
|
|