diff --git a/Projects/Core/CoreKit/Sources/String+Ext.swift b/Projects/Core/CoreKit/Sources/String+Ext.swift index 5bd0b62..8334599 100644 --- a/Projects/Core/CoreKit/Sources/String+Ext.swift +++ b/Projects/Core/CoreKit/Sources/String+Ext.swift @@ -34,4 +34,13 @@ extension String { return "\(firstPart)-\(secondPart)-\(thirdPart)" } } + + public func clipMaxCount(_ maxCount: Int) -> String { + if self.count > maxCount { + let index = self.index(self.startIndex, offsetBy: maxCount) + let formattedText = String(self[.. some View { + content + .keyboardType(keyboardType) + .interactiveDismissDisabled() + .textInputAutocapitalization(.never) + .autocorrectionDisabled() + .speechAnnouncementsQueued(false) + .speechSpellsOutCharacters(false) + } +} + +extension View { + public func flatTextFieldOption(keyboardType: UIKeyboardType = .default) -> some View { + modifier(FlatTextFieldOptionModifier(keyboardType: keyboardType)) + } +} diff --git a/Projects/DesignSystem/DesignCore/Sources/ProfileWidget/WritableProfileWidgetView.swift b/Projects/DesignSystem/DesignCore/Sources/ProfileWidget/WritableProfileWidgetView.swift index 3bc0370..99c1926 100644 --- a/Projects/DesignSystem/DesignCore/Sources/ProfileWidget/WritableProfileWidgetView.swift +++ b/Projects/DesignSystem/DesignCore/Sources/ProfileWidget/WritableProfileWidgetView.swift @@ -9,6 +9,7 @@ import SwiftUI public struct WritableProfileWidgetView: View { + @FocusState private var isfocused: Bool @Binding public var bodyText: String public let title: String public let placeholder: String @@ -22,7 +23,8 @@ public struct WritableProfileWidgetView: View { bodyText: Binding, titleColor: Color, bodyColor: Color, - gradientColors: [Color] + gradientColors: [Color], + focusState: FocusState = .init() ) { self.title = title self.placeholder = placeholder @@ -30,6 +32,7 @@ public struct WritableProfileWidgetView: View { self.titleColor = titleColor self.bodyColor = bodyColor self.gradientColors = gradientColors + self._isfocused = focusState } public var body: some View { @@ -50,14 +53,27 @@ public struct WritableProfileWidgetView: View { Spacer() } Spacer() - TextEditor( - text: $bodyText - ) - .textEditorStyle( - PlainTextEditorStyle() - ) - .typography(.regular_14) - .foregroundStyle(bodyColor) + ZStack(alignment: .topLeading) { + if bodyText.isEmpty { + Text(placeholder) + .typography(.regular_14) + .foregroundStyle( + Color(hex: 0x15394B4D).opacity(0.3) + ) + .padding(.all, 8) + } + + TextEditor( + text: $bodyText + ) + .textEditorStyle( + PlainTextEditorStyle() + ) + .focused($isfocused) + .flatTextFieldOption() + .typography(.regular_14) + .foregroundStyle(bodyColor) + } } .scrollIndicators(.hidden) .padding(.all, 28) @@ -71,13 +87,13 @@ struct PreviewView: View { var body: some View { WritableProfileWidgetView( title: "Title", - placeholder: "Placeholder", + placeholder: "this is Placeholder hahaha dhdhdh 바래보아요", bodyText: $text, titleColor: .black, bodyColor: .red, gradientColors: [.yellow, .green] ) - .frame(width: 200, height: 200) + .frame(width: 300, height: 300) } } diff --git a/Projects/Features/Home/Sources/Profile/ProfileView.swift b/Projects/Features/Home/Sources/Profile/ProfileView.swift index 2e293d6..b49abdc 100644 --- a/Projects/Features/Home/Sources/Profile/ProfileView.swift +++ b/Projects/Features/Home/Sources/Profile/ProfileView.swift @@ -112,7 +112,7 @@ public struct ProfileView: View { .sheet( isPresented: $isPresentWidgetSelectionView, content: { - NavigationView { + NavigationStack { WidgetSelectionView( isPresented: $isPresentWidgetSelectionView ) diff --git a/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingIntent.swift b/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingIntent.swift index 7af73a8..63f7adc 100644 --- a/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingIntent.swift +++ b/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingIntent.swift @@ -32,7 +32,7 @@ extension WidgetWritingIntent { protocol Intentable { // content func onChangedBodyText(_ text: String, maxCount: Int) - func onTapNextButton() + func onTapNextButton(state: WidgetWritingModel.Stateful) // default func onAppear() @@ -48,15 +48,22 @@ extension WidgetWritingIntent { extension WidgetWritingIntent: WidgetWritingIntent.Intentable { // default func onChangedBodyText(_ text: String, maxCount: Int) { - if text.count > maxCount { - return - } - model?.setBodyText(text) + let formattedText = text.clipMaxCount(maxCount) + model?.setBodyText(formattedText) + } + func onAppear() { + model?.setFocusState(true) } - func onAppear() {} func task() async {} // content - func onTapNextButton() {} + func onTapNextButton(state: any WidgetWritingModel.Stateful) { + guard let selectedWidget = state.selectedWidgetType else { return } + // 창닫기 + model?.modalDismiss() + + } + + } diff --git a/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingModel.swift b/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingModel.swift index 4a7c93c..d5cd728 100644 --- a/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingModel.swift +++ b/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingModel.swift @@ -22,6 +22,8 @@ final class WidgetWritingModel: ObservableObject { var textMaxCount: Int { get } var isModalPresented: Bool { get } + var isFocused: Bool { get } + var isCTAButtonEnabled: Bool { get } // default var isLoading: Bool { get } @@ -36,8 +38,13 @@ final class WidgetWritingModel: ObservableObject { @Published var selectedWidgetType: WidgetType? @Published var widgetBodyText = String() @Published var isModalPresented: Bool = true + @Published var isFocused: Bool = false var textMaxCount: Int = 40 + var isCTAButtonEnabled: Bool { + widgetBodyText.count > 4 + } + @Published var isValidated: Bool = false // default @@ -53,6 +60,7 @@ extension WidgetWritingModel: WidgetWritingModel.Stateful {} //MARK: - Actionable protocol WidgetWritingModelActionable: AnyObject { // content + func setFocusState(_ isFocused: Bool) func setBodyText(_ text: String) func setValidation(value: Bool) func setWidgetType(_ widget: WidgetType) @@ -69,6 +77,9 @@ protocol WidgetWritingModelActionable: AnyObject { extension WidgetWritingModel: WidgetWritingModelActionable { // content + func setFocusState(_ isFocused: Bool) { + self.isFocused = isFocused + } func setBodyText(_ text: String) { widgetBodyText = text } diff --git a/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingView.swift b/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingView.swift index f1c2cd9..7109ffd 100644 --- a/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingView.swift +++ b/Projects/Features/Home/Sources/Widget/WidgetWriting/WidgetWritingView.swift @@ -16,6 +16,7 @@ public struct WidgetWritingView: View { @Binding var isPushed: Bool @Binding var isModalPresented: Bool + @FocusState var isFocused: Bool @StateObject var container: MVIContainer @@ -23,7 +24,7 @@ public struct WidgetWritingView: View { private var state: WidgetWritingModel.Stateful { container.model } private var size: CGFloat { - Device.height * 0.3 + Device.height * 0.25 } public init( @@ -54,20 +55,24 @@ public struct WidgetWritingView: View { .padding(.vertical, 20) WritableProfileWidgetView( - title: widget.title, + title: widget.title + widget.emoji, placeholder: widget.exampleText, bodyText: $container.model.widgetBodyText, titleColor: widget.titleColor, bodyColor: widget.bodyColor, - gradientColors: widget.gradationColors + gradientColors: widget.gradationColors, + focusState: _isFocused ) .frame(width: size, height: size) .onChange(of: state.widgetBodyText) { intent.onChangedBodyText( - bodyText, + state.widgetBodyText, maxCount: state.textMaxCount ) } + .onChange(of: state.isFocused) { + self.isFocused = state.isFocused + } } HStack(spacing: 0) { @@ -78,6 +83,13 @@ public struct WidgetWritingView: View { } .typography(.regular_15) Spacer() + + CTABottomButton( + title: "다 썻어요", + isActive: state.isCTAButtonEnabled + ) { + intent.onTapNextButton(state: state) + } } .onChange(of: state.isModalPresented) { isModalPresented = state.isModalPresented diff --git a/Projects/Features/SignUp/Sources/ProfileInput/AuthName/AuthNameInputView.swift b/Projects/Features/SignUp/Sources/ProfileInput/AuthName/AuthNameInputView.swift index fddf345..2aa4a6a 100644 --- a/Projects/Features/SignUp/Sources/ProfileInput/AuthName/AuthNameInputView.swift +++ b/Projects/Features/SignUp/Sources/ProfileInput/AuthName/AuthNameInputView.swift @@ -66,12 +66,7 @@ public struct AuthNameInputView: View { "김위브", text: $inputText ) - .keyboardType(.namePhonePad) - .interactiveDismissDisabled() - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - .speechAnnouncementsQueued(false) - .speechSpellsOutCharacters(false) + .flatTextFieldOption(keyboardType: .namePhonePad) .multilineTextAlignment(.center) .pretendard(weight: ._400, size: 28) .foregroundStyle(DesignCore.Colors.grey500) diff --git a/Projects/Model/Model/Sources/Profile/Widget/WidgetType.swift b/Projects/Model/Model/Sources/Profile/Widget/WidgetType.swift index bd7c3e9..e570ee4 100644 --- a/Projects/Model/Model/Sources/Profile/Widget/WidgetType.swift +++ b/Projects/Model/Model/Sources/Profile/Widget/WidgetType.swift @@ -46,6 +46,25 @@ extension WidgetType { } } + public var emoji: String { + switch self { + case .hobby: return "🏃" + case .style: return "👖" + case .mbti: return "💭" + case .music: return "🎧" + case .body: return "💪" + case .food: return "🍔" + case .movie: return "🎬" + case .drama: return "📺" + case .book: return "📚" + case .travel: return "✈️" + case .alcohol: return "🍷" + case .marriage: return "💍" + case .religion: return "⛪" + case .smoking: return "🚬" + } + } + public var exampleText: String { switch self { case .hobby: