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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58,783 changes: 58,783 additions & 0 deletions RecipesDataset.csv

Large diffs are not rendered by default.

Binary file modified SWFrontUI/.DS_Store
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>ShopwiseFrontEndUI.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>
23 changes: 23 additions & 0 deletions SWFrontUI/ShopwiseFrontEndUI/AuthGateView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// AuthManagerGate.swift
// ShopwiseFrontEndUI
//
// Created by Nicholas Castellanos on 2/2/26.
//

import SwiftUI

struct AuthGateView: View {
@EnvironmentObject var auth: AuthManager

var body: some View {
Group {
if auth.isSignedIn {
// ✅ Your main app view (what you showed in screenshot)
ContentView()
} else {
AuthView()
}
}
}
}
47 changes: 47 additions & 0 deletions SWFrontUI/ShopwiseFrontEndUI/AuthManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// Untitled.swift
// ShopwiseFrontEndUI
//
// Created by Nicholas Castellanos on 2/2/26.
//

import SwiftUI
import Combine

@MainActor
final class AuthManager: ObservableObject {
@Published var isSignedIn: Bool = false
@Published var userEmail: String? = nil

func signIn(email: String, password: String) async throws {
guard !email.isEmpty, !password.isEmpty else {
throw AuthError.missingFields
}
self.userEmail = email
self.isSignedIn = true
}

func signUp(name: String, email: String, password: String) async throws {
guard !name.isEmpty, !email.isEmpty, !password.isEmpty else {
throw AuthError.missingFields
}
self.userEmail = email
self.isSignedIn = true
}

func signOut() {
userEmail = nil
isSignedIn = false
}

enum AuthError: LocalizedError {
case missingFields
var errorDescription: String? { "Please fill out all fields." }
}
}


#Preview {
AuthView()
.environmentObject(AuthManager())
}
140 changes: 140 additions & 0 deletions SWFrontUI/ShopwiseFrontEndUI/AuthView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import SwiftUI

struct AuthView: View {
@EnvironmentObject private var auth: AuthManager

enum Mode { case login, signup }
@State private var mode: Mode = .login

@State private var name = ""
@State private var email = ""
@State private var password = ""

@State private var isLoading = false
@State private var errorMessage: String?

var body: some View {
ZStack {
Color(.systemBlue).opacity(0.12).ignoresSafeArea()

VStack {
Spacer(minLength: 30)

VStack(spacing: 18) {
// Header
VStack(spacing: 10) {
Image(systemName: "cart")
.font(.system(size: 42, weight: .semibold))
.foregroundStyle(.blue)

Text("ShopWise")
.font(.title3)
.foregroundStyle(.blue)
.bold()
}
.padding(.top, 10)

// Login / Sign Up toggle
Picker("", selection: $mode) {
Text("Login").tag(Mode.login)
Text("Sign Up").tag(Mode.signup)
}
.pickerStyle(.segmented)

// Fields
VStack(spacing: 12) {
if mode == .signup {
LabeledField(title: "Name") {
TextField("Enter your name", text: $name)
.textInputAutocapitalization(.words)
.autocorrectionDisabled()
}
}

LabeledField(title: "Email") {
TextField("Enter your email", text: $email)
.textInputAutocapitalization(.never)
.keyboardType(.emailAddress)
.autocorrectionDisabled()
}

LabeledField(title: "Password") {
SecureField(mode == .signup ? "Create a password" : "Enter your password",
text: $password)
}
}

if let errorMessage {
Text(errorMessage)
.foregroundStyle(.red)
.font(.callout)
.frame(maxWidth: .infinity, alignment: .leading)
}

Button {
Task { await submit() }
} label: {
HStack {
if isLoading { ProgressView() }
Text(mode == .signup ? "Sign Up" : "Login")
}
.frame(maxWidth: .infinity)
.padding(.vertical, 12)
}
.buttonStyle(.borderedProminent)
.disabled(isLoading)

}
.padding(20)
.background(
RoundedRectangle(cornerRadius: 18, style: .continuous)
.fill(.white)
)
.padding(.horizontal, 24)

Spacer()
}
}
}

@MainActor
private func submit() async {
isLoading = true
errorMessage = nil

do {
switch mode {
case .login:
try await auth.signIn(email: email, password: password)
case .signup:
// If you don’t have signUp yet, temporarily just sign in:
// try await auth.signIn(email: email, password: password)

try await auth.signUp(name: name, email: email, password: password)
}
} catch {
errorMessage = error.localizedDescription
}

isLoading = false
}
}

private struct LabeledField<Content: View>: View {
let title: String
@ViewBuilder var content: () -> Content

var body: some View {
VStack(alignment: .leading, spacing: 6) {
Text(title)
.font(.footnote)
.foregroundStyle(.secondary)

content()
.padding(10)
.background(Color(.systemGray6))
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
4 changes: 4 additions & 0 deletions SWFrontUI/ShopwiseFrontEndUI/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,7 @@ struct ContentView: View {
.modelContainer(for: Item.self, inMemory: true)
}

#Preview {
AuthView()
.environmentObject(AuthManager())
}
20 changes: 18 additions & 2 deletions SWFrontUI/ShopwiseFrontEndUI/ShopwiseFrontEndUIApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,32 @@
// ShopwiseFrontEndUI
//
// Created by James Chang on 1/13/26.
// Edited by Nicholas Castellanos

//import SwiftUI
//import SwiftData
//
//@main
//struct Shopwise: App {
// var body: some Scene {
// WindowGroup {
// ContentView()
// }
// }
//}


import SwiftUI
import SwiftData

@main
struct Shopwise: App {
struct ShopwiseFrontEndUIApp: App {
@StateObject private var auth = AuthManager()

var body: some Scene {
WindowGroup {
ContentView()
AuthGateView()
.environmentObject(auth)
}
}
}
Loading