Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Connect WelcomeView and WelcomeViewAddVehicle to App Flow #301

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"colors" : [
maartinj marked this conversation as resolved.
Show resolved Hide resolved
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x00",
"green" : "0x00",
"red" : "0x00"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x00",
"green" : "0x00",
"red" : "0x00"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
12 changes: 6 additions & 6 deletions Basic-Car-Maintenance/Shared/BasicCarMaintenanceApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ struct BasicCarMaintenanceApp: App {
@State private var actionService = ActionService.shared
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

// Logic to load Onboarding screen when app was first launched
// @AppStorage("isFirstTime") private var isFirstTime: Bool = true
// Logic to load OnboardingScreen when app first launch
@AppStorage("isFirstTime") private var isFirstTime: Bool = true

var body: some Scene {
WindowGroup {
Expand All @@ -25,10 +25,10 @@ struct BasicCarMaintenanceApp: App {
.task {
try? Tips.configure()
}
// .sheet(isPresented: $isFirstTime) {
// WelcomeView()
// .interactiveDismissDisabled()
// }
.sheet(isPresented: $isFirstTime) {
WelcomeView()
.interactiveDismissDisabled()
}
}
}
}
Expand Down
20 changes: 16 additions & 4 deletions Basic-Car-Maintenance/Shared/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,9 @@
}
}
}
},
"Congratulations! 🎉 🚙" : {

},
"Continue" : {

Expand Down Expand Up @@ -2480,6 +2483,9 @@
}
}
},
"From now on, next screen will be the main app screen." : {
"comment" : "Shows popup when completed Onboarding tutorial"
},
"GitHub Repo" : {
"comment" : "Link to the Basic Car Maintenance GitHub repo.",
"localizations" : {
Expand Down Expand Up @@ -2741,6 +2747,9 @@
}
}
}
},
"Locally Saved Vehicle" : {

},
"Logged in anonymously with ID: %@" : {
"localizations" : {
Expand Down Expand Up @@ -5005,6 +5014,12 @@
}
}
}
},
"Vehicle %@" : {

},
"Vehicle %@ cannot be empty! 🚗" : {

},
"Vehicle Color" : {
"localizations" : {
Expand Down Expand Up @@ -5784,9 +5799,6 @@
}
}
}
},
"Welcome 🥳" : {

},
"Welcome to" : {

Expand Down Expand Up @@ -5863,4 +5875,4 @@
}
},
"version" : "1.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,99 +9,177 @@ import SwiftUI

struct WelcomeViewAddVehicle: View {

// Logic to remember Onboarding screen to not load again when app is launched
// @AppStorage("isFirstTime") private var isFirstTime: Bool = true
// Logic to remember OnboardingScreen to not load again when app is launched
@AppStorage("isFirstTime") private var isFirstTime: Bool = true
@AppStorage("vehicleName") private var vehicleName: String = ""
@AppStorage("vehicleMake") private var vehicleMake: String = ""
@AppStorage("vehicleModel") private var vehicleModel: String = ""
@Environment(\.dismiss) var dismiss

@State private var vehicleName: String = ""
@State private var vehicleMake: String = ""
@State private var vehicleModel: String = ""
@State private var validationAlertName: Bool = false
@State private var validationAlertMake: Bool = false
@State private var validationAlertModel: Bool = false
@State private var onboardingViewCompletedAlert: Bool = false
maartinj marked this conversation as resolved.
Show resolved Hide resolved

var body: some View {
VStack(spacing: 15) {
maartinj marked this conversation as resolved.
Show resolved Hide resolved
VStack {
Text("Add the details below")
HStack(spacing: 5) {
Text("about")
Text("your vehicle")
.foregroundStyle(Color("basicGreen"))
}
headerView
vehicleDetailsView
bottomText
Spacer(minLength: 10)
addVehicleButton
}
.font(.largeTitle.bold())
.multilineTextAlignment(.center)
.padding(.top, 65)
.padding(.bottom, 15)

VStack {
Image(systemName: "car.side.lock.open")
.font(.system(size: 45))
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(UIColor.secondarySystemBackground).ignoresSafeArea())
.navigationBarBackButtonHidden(true)
.toolbar { backButton }
}

private var headerView: some View {
VStack {
Text("Add the details below")
HStack(spacing: 5) {
Text("about")
Text("your vehicle")
.foregroundStyle(Color("basicGreen"))
maartinj marked this conversation as resolved.
Show resolved Hide resolved

List {
HStack {
Text("Name")
Spacer()
.frame(width: 40)
TextField("Vehicle Name", text: $vehicleName)
}

HStack {
Text("Make")
Spacer()
.frame(width: 45)
TextField("Vehicle Make", text: $vehicleMake)
}
HStack {
Text("Model")
Spacer()
.frame(width: 40)
TextField("Vehicle Model", text: $vehicleModel)
}
}
.frame(maxHeight: 200)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 15)

Text("You can edit more data about the vehicle in the 'Settings' tab.")
.foregroundStyle(.gray)
.padding(.horizontal, 25)
}
.font(.largeTitle.bold())
maartinj marked this conversation as resolved.
Show resolved Hide resolved
.multilineTextAlignment(.center)
.padding(.top, 65)
.padding(.bottom, 15)
}

private var vehicleDetailsView: some View {
VStack {
Image(systemName: "car.side.lock.open")
.font(.system(size: 45))
.foregroundStyle(Color("basicGreen"))

Spacer(minLength: 10)
List {
vehicleDetailRow(title: "Name", text: $vehicleName, alert: $validationAlertName)
vehicleDetailRow(title: "Make", text: $vehicleMake, alert: $validationAlertMake)
vehicleDetailRow(title: "Model", text: $vehicleModel, alert: $validationAlertModel)
}
.frame(maxHeight: 200)
.scrollContentBackground(.hidden)
}
.padding(.horizontal, 15)
}

private func vehicleDetailRow(title: String, text: Binding<String>, alert: Binding<Bool>) -> some View {
LabeledContent {
TextField("Vehicle \(title)", text: text)
.alert(
"Vehicle \(title) cannot be empty! 🚗",
isPresented: alert
) {
Button("OK", role: .cancel) {}
}
.frame(width: 200)
} label: {
HStack {
Text(title)
Spacer()
}
}
.showClearButton(text)
}

private var bottomText: some View {
Text("You can edit more data about the vehicle in the 'Settings' tab.")
.foregroundStyle(.gray)
.padding(.horizontal, 25)
}

private var addVehicleButton: some View {
Button {
addVehicle()
} label: {
Text("Add Vehicle")
.fontWeight(.bold)
.foregroundStyle(.white)
.frame(maxWidth: .infinity)
.padding(.vertical, 14)
.background(Color("basicGreen").gradient, in: .rect(cornerRadius: 12))
.contentShape(.rect)
}
.padding(15)
.padding(.horizontal, 15)
.alert(
Text("Congratulations! 🎉 🚙"),
isPresented: $onboardingViewCompletedAlert
) {
Button("OK", role: .cancel, action: {
isFirstTime = false
})
} message: {
Text(
"From now on, next screen will be the main app screen.",
comment: "Shows popup when completed Onboarding tutorial"
)
}
maartinj marked this conversation as resolved.
Show resolved Hide resolved
}

func addVehicle() {
if vehicleName.isEmpty {
validationAlertName = true
} else if vehicleMake.isEmpty {
validationAlertMake = true
} else if vehicleModel.isEmpty {
validationAlertModel = true
} else {
UserDefaults.standard.set(vehicleName, forKey: "vehicleName")
UserDefaults.standard.set(vehicleMake, forKey: "vehicleMake")
UserDefaults.standard.set(vehicleModel, forKey: "vehicleModel")
maartinj marked this conversation as resolved.
Show resolved Hide resolved

// isFirstTime = false
onboardingViewCompletedAlert = true
}
}

private var backButton: some ToolbarContent {
maartinj marked this conversation as resolved.
Show resolved Hide resolved
ToolbarItem(placement: .topBarLeading) {
Button {
// isFirstTime = false
dismiss()
} label: {
Text("Welcome 🥳")
.fontWeight(.bold)
.foregroundStyle(.white)
.frame(maxWidth: .infinity)
.padding(.vertical, 14)
.background(Color("basicGreen").gradient, in: .rect(cornerRadius: 12))
.contentShape(.rect)
HStack {
Image(systemName: "arrow.left.circle")
Text("Back")
}
.tint(Color("basicGreen"))
}
.padding(15)
.padding(.horizontal, 15)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background {
Color(UIColor.secondarySystemBackground)
.ignoresSafeArea()
}
.navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button {
dismiss()
} label: {
}
}

struct TextFieldClearButton: ViewModifier {
maartinj marked this conversation as resolved.
Show resolved Hide resolved
maartinj marked this conversation as resolved.
Show resolved Hide resolved
@Binding var text: String

func body(content: Content) -> some View {
content
.overlay {
if !text.isEmpty {
HStack {
Image(systemName: "arrow.left.circle")
Text("Back")
Spacer()
Button {
text = ""
} label: {
Image(systemName: "multiply.circle.fill")
.imageScale(.medium)
}
.foregroundColor(.secondary)
.padding(.trailing, 4)
}
.tint(Color("basicGreen"))
}
}
}
}
}

extension View {
func showClearButton(_ text: Binding<String>) -> some View {
self.modifier(TextFieldClearButton(text: text))
}
}

Expand Down
Loading
Loading