Skip to content

Instantly share code, notes, and snippets.

@jspence1234
Last active February 8, 2025 03:16
Show Gist options
  • Save jspence1234/c442df89110e077725e5217a6b176624 to your computer and use it in GitHub Desktop.
Save jspence1234/c442df89110e077725e5217a6b176624 to your computer and use it in GitHub Desktop.
//
// JacobsWorkApp.swift
// JacobsWorkApp
//
// Created by Jacob Spence on [Date]
//
import SwiftUI
import SwiftData
@main
struct JacobsWorkApp: App {
let modelContainer: ModelContainer
init() {
do {
// Provide model types as a variadic list, now including PullSheet and PullSheetItem
self.modelContainer = try ModelContainer(
for:
TodoItem.self,
StickyNote.self,
Note.self,
Part.self,
PullSheet.self,
PullSheetItem.self
)
} catch {
fatalError("Failed to initialize ModelContainer: \(error.localizedDescription)")
}
}
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(modelContainer)
.task {
// Run CSV importer if needed
let importer = PartImporter(container: modelContainer)
await importer.importCSVIfNeeded()
}
}
}
}
//
// Note.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
import SwiftData
@Model
final class Note: Identifiable {
var title: String
var content: String
var dateCreated: Date
init(title: String, content: String, dateCreated: Date = Date()) {
self.title = title
self.content = content
self.dateCreated = dateCreated
}
}
//
// NoteViewModel.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
import Combine
import Foundation
class NoteViewModel: ObservableObject {
@Published var notes: [Note] = []
/// Adds a new note to the array.
func addNote(title: String, content: String) {
let newNote = Note(title: title, content: content)
notes.append(newNote)
}
/// Deletes notes at the given offsets (used by .onDelete).
func deleteNotes(at offsets: IndexSet) {
notes.remove(atOffsets: offsets)
}
/// Updates an existing note’s title/content if it still exists in the array.
func updateNote(note: Note, title: String, content: String) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
notes[index].title = title
notes[index].content = content
}
}
}
//
// Part.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
import SwiftData
@Model
final class Part: Identifiable {
var partNumber: String
var partDescription: String
var binLocation: String
init(partNumber: String, partDescription: String, binLocation: String) {
self.partNumber = partNumber
self.partDescription = partDescription
self.binLocation = binLocation
}
}
import SwiftUI
import SwiftData
@Model
final class PullSheet: ObservableObject, Identifiable {
var id: UUID
var title: String
var items: [PullSheetItem]
init(title: String, items: [PullSheetItem] = []) {
self.id = UUID()
self.title = title
self.items = items
}
}
//
// PullSheetItem.swift
// JacobsWorkApp
//
// Created by Jacob Spence on [Date]
//
import SwiftUI
import SwiftData
@Model
final class PullSheetItem: Identifiable {
var id: UUID
var part: Part
var quantity: Int
init(part: Part, quantity: Int) {
self.id = UUID()
self.part = part
self.quantity = quantity
}
}
//
// StickyNote.swift
// JacobsWorkApp
//
// Created by Jacob Spence on [Date]
//
import SwiftUI
import SwiftData
@Model
final class StickyNote: Identifiable {
var id: UUID
var textContent: String?
var imageData: Data?
var dateCreated: Date
var isCompleted: Bool
init(
textContent: String? = nil,
imageData: Data? = nil,
dateCreated: Date = Date(),
isCompleted: Bool = false
) {
self.id = UUID()
self.textContent = textContent
self.imageData = imageData
self.dateCreated = dateCreated
self.isCompleted = isCompleted
}
}
//
// TodoItem.swift
// JacobsWorkApp
//
// Created by Jacob Spence on [Date]
//
import SwiftUI
import SwiftData
@Model
final class TodoItem: Identifiable {
var title: String
var isCompleted: Bool
var dueDate: Date? // Optional due date
var isRecurring: Bool // false: one-time, true: every day
init(title: String, isCompleted: Bool = false, dueDate: Date? = nil, isRecurring: Bool = false) {
self.title = title
self.isCompleted = isCompleted
self.dueDate = dueDate
self.isRecurring = isRecurring
}
}
//
// TodoViewModel.swift
// JacobsWorkApp
//
// Created by Jacob Spence on [Date]
//
import SwiftUI
class TodoViewModel: ObservableObject {
@Published var todos: [TodoItem] = []
func addTodo(title: String, isRecurring: Bool = false) {
todos.append(TodoItem(title: title, isRecurring: isRecurring))
}
func toggleTodoCompletion(todo: TodoItem) {
todo.isCompleted.toggle()
}
func updateTodo(todo: TodoItem, title: String, isRecurring: Bool) {
if let index = todos.firstIndex(where: { $0.id == todo.id }) {
todos[index].title = title
todos[index].isRecurring = isRecurring
}
}
}
//
// CloudSyncManager.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import Foundation
import CloudKit
class CloudSyncManager {
// Code to manage iCloud/CloudKit synchronization
}
//
// Helpers.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import Foundation
struct Helpers {
// General utility functions can be added here
}
import SwiftData
import Foundation
@MainActor
class PartImporter {
let container: ModelContainer
init(container: ModelContainer) {
self.container = container
}
func importCSVIfNeeded() async {
do {
let context = container.mainContext
let fetchDescriptor = FetchDescriptor<Part>(sortBy: [])
let existingParts = try context.fetch(fetchDescriptor)
if existingParts.isEmpty {
if let url = Bundle.main.url(forResource: "parts", withExtension: "csv") {
let data = try Data(contentsOf: url)
if let csvString = String(data: data, encoding: .utf8) {
// Split the CSV string by newlines to get each row
let lines = csvString.components(separatedBy: .newlines)
// Assume the first line is the header, so skip it.
try context.transaction {
for line in lines.dropFirst() where !line.isEmpty {
// Split each line by comma
let columns = line.components(separatedBy: ",")
// Make sure you have at least 3 columns: partNumber, partDescription, binLocation
if columns.count >= 3 {
let part = Part(
partNumber: columns[0],
partDescription: columns[1],
binLocation: columns[2]
)
context.insert(part)
}
}
}
}
}
}
} catch {
print("Error importing CSV: \(error.localizedDescription)")
}
}
}
//
// AddFromPartsView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct AddFromPartsView: View {
@State private var searchText: String = ""
var body: some View {
VStack {
HStack {
Text("Add Item from Parts")
.font(.largeTitle)
Spacer()
Button("<") { }
}
.padding()
TextField("Search Parts", text: $searchText)
.padding()
.textFieldStyle(RoundedBorderTextFieldStyle())
List {
// Sample parts list filtered by searchText
Text("12345 - Widget A: High quality widget, Bin: 3B")
Text("22345 - Numeric Sensor: Precision measurement, Bin: 1A")
Text("32345 - Dumbbell Set: Weighted equipment")
}
}
}
}
import SwiftUI
import SwiftData
struct AddPullSheetItemView: View {
@ObservedObject var pullSheet: PullSheet
@Environment(\.modelContext) private var modelContext
@Environment(\.dismiss) private var dismiss
@State private var searchText: String = ""
@State private var selectedPart: Part? = nil
@State private var quantity: String = ""
@Query(sort: \Part.partNumber, animation: .default) private var parts: [Part]
private var filteredParts: [Part] {
if searchText.isEmpty {
return parts
} else {
let q = searchText.lowercased()
return parts.filter {
$0.partNumber.lowercased().contains(q) ||
$0.partDescription.lowercased().contains(q)
}
}
}
var body: some View {
NavigationStack {
VStack {
if selectedPart == nil {
TextField("Search Parts", text: $searchText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
List(filteredParts, id: \.id) { part in
Button(action: {
selectedPart = part
}) {
VStack(alignment: .leading) {
Text(part.partNumber)
.font(.headline)
Text(part.partDescription)
.font(.subheadline)
}
}
}
} else {
Form {
Section(header: Text("Selected Part")) {
if let part = selectedPart {
Text(part.partNumber)
.font(.headline)
Text(part.partDescription)
.font(.subheadline)
}
}
Section(header: Text("Quantity")) {
TextField("Quantity", text: $quantity)
.keyboardType(.numberPad)
}
}
.navigationTitle("Add Item")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
guard let part = selectedPart,
let qty = Int(quantity),
qty > 0 else { return }
let newItem = PullSheetItem(part: part, quantity: qty)
pullSheet.items.append(newItem)
modelContext.insert(newItem)
dismiss()
}
}
ToolbarItem(placement: .navigationBarLeading) {
Button("Back") {
selectedPart = nil
quantity = ""
}
}
}
}
}
.navigationTitle(selectedPart == nil ? "Select Part" : "Add Item")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
}
}
}
}
}
//
// AnalyticsView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct AnalyticsView: View {
var body: some View {
VStack {
Text("Analytics")
.font(.largeTitle)
// Placeholder charts and stats
Text("[Chart: Task Completion Rate Over Time]")
.padding()
Text("[Chart: Orders Placed Per Day]")
.padding()
Text("Summary Stats: Total Tasks, Completed Orders")
.padding()
HStack {
Button("Filter by Date") { }
Spacer()
Button("Export Report") { }
}
.padding()
}
}
}
import SwiftUI
import SwiftData
struct ContentView: View {
@StateObject private var todoViewModel = TodoViewModel()
@StateObject private var noteViewModel = NoteViewModel() // For other notes if needed
var body: some View {
TabView {
NavigationStack {
DashboardView(todoViewModel: todoViewModel)
}
.tabItem {
Image(systemName: "house.fill")
Text("Dashboard")
}
NavigationStack {
TodoListView() // Your tasks view
.environmentObject(todoViewModel)
}
.tabItem {
Image(systemName: "checkmark.circle.fill")
Text("Tasks")
}
NavigationStack {
StickyNotesTabView() // NEW: Dedicated Sticky Notes tab
}
.tabItem {
Image(systemName: "square.and.pencil")
Text("Sticky Notes")
}
NavigationStack {
PartLookupView() // Parts catalog view
}
.tabItem {
Image(systemName: "magnifyingglass")
Text("Parts")
}
NavigationStack {
PullSheetListView() // PullSheets view
}
.tabItem {
Image(systemName: "doc.on.doc")
Text("PullSheets")
}
NavigationStack {
SettingsView()
}
.tabItem {
Image(systemName: "gearshape.fill")
Text("Settings")
}
}
}
}
import SwiftUI
import SwiftData
struct DashboardView: View {
@ObservedObject var todoViewModel: TodoViewModel
@State private var newTaskTitle: String = ""
@State private var newTaskRecurring: Bool = false // false = one-time, true = every day
@State private var selectedTask: TodoItem? = nil
@State private var selectedStickyNote: StickyNote? = nil // new state for sticky note selection
@Query private var stickyNotes: [StickyNote]
@Environment(\.modelContext) private var modelContext
@State private var showNotepadSheet: Bool = false
var body: some View {
NavigationStack {
HStack(alignment: .top) {
// Left column: Sticky Notes Grid with onSelect closure
StickyNoteGridView(stickyNotes: stickyNotes, onSelect: { note in
selectedStickyNote = note
})
.frame(maxWidth: .infinity)
// Right column: Task list with inline addition
VStack(alignment: .leading) {
HStack {
TextField("New Task", text: $newTaskTitle)
.textFieldStyle(RoundedBorderTextFieldStyle())
Picker("", selection: $newTaskRecurring) {
Text("One-Time").tag(false)
Text("Every Day").tag(true)
}
.pickerStyle(SegmentedPickerStyle())
Button(action: {
guard !newTaskTitle.isEmpty else { return }
todoViewModel.addTodo(title: newTaskTitle, isRecurring: newTaskRecurring)
newTaskTitle = ""
newTaskRecurring = false
}, label: {
Image(systemName: "plus.circle.fill")
.font(.title)
})
}
.padding()
ScrollView {
LazyVStack(spacing: 10) {
ForEach(todoViewModel.todos) { task in
TodoCardView(task: task)
.onTapGesture {
selectedTask = task
}
}
}
.padding()
}
.sheet(item: $selectedTask) { task in
TodoDetailView(task: task, todoViewModel: todoViewModel)
}
}
.frame(maxWidth: .infinity)
}
.navigationTitle("Dashboard")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
showNotepadSheet.toggle()
}) {
Image(systemName: "square.and.pencil")
}
}
}
.fullScreenCover(isPresented: $showNotepadSheet) {
FullScreenNotepadView()
}
// New fullScreenCover to present the sticky note detail when one is tapped
.fullScreenCover(item: $selectedStickyNote) { note in
StickyNoteDetailView(note: note)
}
}
}
}
//
// DrawingNoteView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
import PencilKit
struct DrawingNoteView: View {
@State private var canvasView = PKCanvasView()
@State private var tool: PKTool = PKInkingTool(.pen, color: .black, width: 3)
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
// The Canvas
PencilCanvasView(canvasView: $canvasView, tool: $tool)
.background(Color(UIColor.secondarySystemBackground))
.cornerRadius(10)
.padding()
// The Save Button
Button("Save") {
let drawingImage = captureDrawing()
if let filename = saveImageToDocuments(drawingImage) {
print("Saved drawing as \(filename)")
}
dismiss() // Pop back in the navigation stack
}
.padding()
}
.navigationTitle("Drawing Note")
}
/// Renders the PencilKit drawing into a UIImage
private func captureDrawing() -> UIImage {
let bounds = canvasView.bounds
return canvasView.drawing.image(from: bounds, scale: UIScreen.main.scale)
}
/// Saves the UIImage to the app’s Documents directory and returns the filename if successful
private func saveImageToDocuments(_ image: UIImage) -> String? {
guard let data = image.pngData() else { return nil }
let filename = "drawing_\(UUID().uuidString).png"
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsURL.appendingPathComponent(filename)
do {
try data.write(to: fileURL)
return filename
} catch {
print("Error saving image: \(error.localizedDescription)")
return nil
}
}
}
//
// EditRecurringTaskView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct EditRecurringTaskView: View {
var body: some View {
VStack {
HStack {
Button("< Back") { }
Spacer()
Text("Edit Recurring Task")
.font(.headline)
Spacer()
}
.padding()
Form {
TextField("Task Title", text: .constant(""))
TextField("Description", text: .constant(""))
Picker("Frequency", selection: .constant("Daily")) {
Text("Daily").tag("Daily")
Text("Weekly").tag("Weekly")
Text("Monthly").tag("Monthly")
}
DatePicker("Next Due Date", selection: .constant(Date()))
}
HStack {
Button("Save Changes") { }
Spacer()
Button("Cancel") { }
}
.padding()
}
}
}
import SwiftUI
import PencilKit
import SwiftData
struct FullScreenNotepadView: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.modelContext) private var modelContext
@State private var canvasView = PKCanvasView()
@State private var textContent: String = ""
@State private var selectedColor: Color = .black
@State private var selectedWidth: CGFloat = 3
@State private var tool: PKTool = PKInkingTool(.pen, color: .black, width: 3)
var body: some View {
NavigationStack {
VStack(spacing: 10) {
Text("Full Screen Notepad")
.font(.title2)
.fontWeight(.bold)
TextField("Enter note text...", text: $textContent)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
PencilCanvasView(canvasView: $canvasView, tool: $tool)
.frame(height: 300)
.background(Color.white)
.cornerRadius(15)
.shadow(radius: 5)
toolSelectionControls()
HStack {
Button("Save") {
saveStickyNote()
dismiss()
}
.buttonStyle(.borderedProminent)
Button("Clear") {
clearCanvas()
}
.buttonStyle(.bordered)
.tint(.red)
Button("Close") {
dismiss()
}
.buttonStyle(.bordered)
}
.padding()
}
.navigationTitle("Notepad")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
}
}
}
.ignoresSafeArea() // Ensures a full-screen experience
}
private func saveStickyNote() {
let imageData = canvasView.drawing.dataRepresentation()
let note = StickyNote(
textContent: textContent,
imageData: imageData,
dateCreated: Date(),
isCompleted: false
)
modelContext.insert(note)
}
private func clearCanvas() {
canvasView.drawing = PKDrawing()
}
private func toolSelectionControls() -> some View {
HStack {
ColorPicker("Color", selection: $selectedColor)
.onChange(of: selectedColor) { newValue in
tool = PKInkingTool(.pen, color: UIColor(newValue), width: selectedWidth)
}
Slider(value: $selectedWidth, in: 1...10, step: 1)
.onChange(of: selectedWidth) { newValue in
tool = PKInkingTool(.pen, color: UIColor(selectedColor), width: newValue)
}
}
.padding()
}
}
import SwiftUI
import SwiftData
struct NewPullSheetView: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.modelContext) private var modelContext
@State private var title: String = ""
var body: some View {
NavigationStack {
Form {
Section(header: Text("Pull Sheet Title")) {
TextField("Title", text: $title)
}
}
.navigationTitle("New Pull Sheet")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
guard !title.isEmpty else { return }
let newSheet = PullSheet(title: title)
modelContext.insert(newSheet)
dismiss()
}
}
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
}
}
}
}
}
//
// NoteDetailView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct NoteDetailView: View {
var note: Note
@ObservedObject var noteViewModel: NoteViewModel
@State private var title: String = ""
@State private var content: String = ""
var body: some View {
Form {
Section(header: Text("Title")) {
TextField("Title", text: $title)
}
Section(header: Text("Content")) {
TextField("Content", text: $content)
}
}
.navigationTitle("Edit Note")
.onAppear {
title = note.title
content = note.content
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
noteViewModel.updateNote(note: note, title: title, content: content)
}
}
}
}
}
struct NoteDetailView_Previews: PreviewProvider {
static var previews: some View {
let sampleNote = Note(title: "Sample Note", content: "Sample content")
NavigationView {
NoteDetailView(note: sampleNote, noteViewModel: NoteViewModel())
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
//
// NotepadView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct NotepadView: View {
var body: some View {
VStack {
HStack {
Text("Notepad")
.font(.largeTitle)
Spacer()
// Save, Undo, Redo icons could be added here
}
.padding()
TextEditor(text: .constant("Write your note here..."))
.padding()
HStack {
Button("Pen") { }
Button("Highlighter") { }
Button("Eraser") { }
Button("Color") { }
}
.padding()
}
}
}
//
// NotesView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
import SwiftData
struct NotesView: View {
@Query private var stickyNotes: [StickyNote]
@ObservedObject var noteViewModel: NoteViewModel
var body: some View {
List {
ForEach(stickyNotes) { note in
HStack {
if let imageData = note.imageData, let uiImage = UIImage(data: imageData) {
Image(uiImage: uiImage)
.resizable()
.scaledToFit()
.frame(width: 60, height: 60)
.cornerRadius(8)
}
VStack(alignment: .leading) {
if let text = note.textContent {
Text(text)
.font(.headline)
}
Text(note.dateCreated, style: .date)
.font(.caption)
.foregroundColor(.gray)
}
}
}
}
.navigationTitle("Sticky Notes")
}
}
//
// OrdersView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct OrdersView: View {
var body: some View {
NavigationView {
VStack {
Text("Orders")
.font(.largeTitle)
.padding()
List {
ForEach(0..<5) { index in
HStack {
Image(systemName: "bag")
.foregroundColor(.blue)
VStack(alignment: .leading) {
Text("Order #\(index + 1)")
.font(.headline)
Text("Order details here")
.font(.subheadline)
.foregroundColor(.secondary)
}
}
.padding(.vertical, 4)
}
}
}
.navigationTitle("Orders")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct OrdersView_Previews: PreviewProvider {
static var previews: some View {
OrdersView()
}
}
import SwiftUI
struct PartDetailView: View {
let part: Part
var body: some View {
Form {
Section(header: Text("Part Info")) {
Text("Part Number: \(part.partNumber)")
Text("Description: \(part.partDescription)")
Text("Bin: \(part.binLocation)")
}
}
.navigationTitle("Part Detail")
.navigationBarTitleDisplayMode(.inline)
}
}
import SwiftUI
import SwiftData
struct PartLookupView: View {
@State private var searchText: String = ""
@Query(sort: \Part.partNumber, animation: .default) private var parts: [Part]
private var filteredParts: [Part] {
if searchText.isEmpty {
return parts
} else {
let q = searchText.lowercased()
return parts.filter {
$0.partNumber.lowercased().contains(q) ||
$0.partDescription.lowercased().contains(q)
}
}
}
var body: some View {
List(filteredParts, id: \.id) { part in
NavigationLink(destination: PartDetailView(part: part)) {
VStack(alignment: .leading) {
Text(part.partNumber)
.font(.headline)
Text(part.partDescription)
.font(.subheadline)
Text("Bin: \(part.binLocation)")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
.navigationTitle("Parts Catalog")
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
}
}
import SwiftUI
import PencilKit
struct PencilCanvasView: UIViewRepresentable {
@Binding var canvasView: PKCanvasView
@Binding var tool: PKTool
func makeUIView(context: Context) -> PKCanvasView {
canvasView.drawingPolicy = .anyInput
canvasView.tool = tool
return canvasView
}
func updateUIView(_ uiView: PKCanvasView, context: Context) {
uiView.tool = tool
}
}
import SwiftUI
import SwiftData
struct PullSheetDetailView: View {
@ObservedObject var pullSheet: PullSheet
@Environment(\.modelContext) private var modelContext
@State private var showAddItemSheet = false
var body: some View {
Form {
Section(header: Text("Pull Sheet Items")) {
ForEach(pullSheet.items) { item in
HStack {
VStack(alignment: .leading) {
Text(item.part.partNumber)
.font(.headline)
Text(item.part.partDescription)
.font(.subheadline)
}
Spacer()
Text("Qty: \(item.quantity)")
}
.swipeActions {
Button(role: .destructive) {
modelContext.delete(item)
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
}
.navigationTitle(pullSheet.title)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: { showAddItemSheet.toggle() }) {
Image(systemName: "plus")
}
}
}
.sheet(isPresented: $showAddItemSheet) {
AddPullSheetItemView(pullSheet: pullSheet)
}
}
}
import SwiftUI
import SwiftData
struct PullSheetListView: View {
@Query private var pullSheets: [PullSheet]
@Environment(\.modelContext) private var modelContext
@State private var showNewPullSheetSheet = false
var body: some View {
NavigationStack {
List {
ForEach(pullSheets) { pullSheet in
NavigationLink(destination: PullSheetDetailView(pullSheet: pullSheet)) {
Text(pullSheet.title)
}
.swipeActions {
Button(role: .destructive) {
modelContext.delete(pullSheet)
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
.navigationTitle("Pull Sheets")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: { showNewPullSheetSheet.toggle() }) {
Image(systemName: "plus")
}
}
}
.sheet(isPresented: $showNewPullSheetSheet) {
NewPullSheetView()
}
}
}
}
//
// PullSheetsView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct PullSheetsView: View {
var body: some View {
VStack {
Text("Pull Sheets")
.font(.largeTitle)
.padding()
Text("Pull Sheets functionality goes here.")
.padding()
}
.navigationTitle("Pull Sheets")
}
}
struct PullSheetsView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
PullSheetsView()
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
//
// QuickNoteView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct QuickNoteView: View {
var body: some View {
VStack {
Text("Quick Note")
.font(.headline)
TextEditor(text: .constant("Start writing here..."))
.frame(height: 100)
.padding()
}
}
}
//
// SettingsView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct SettingsView: View {
@State private var sortOption: String = "Date"
@State private var theme: String = "Light"
var body: some View {
Form {
Section(header: Text("Sorting")) {
Picker("Sort By", selection: $sortOption) {
Text("Date").tag("Date")
Text("Title").tag("Title")
Text("Status").tag("Status")
}
.pickerStyle(SegmentedPickerStyle())
}
Section(header: Text("Appearance")) {
Picker("Theme", selection: $theme) {
Text("Light").tag("Light")
Text("Dark").tag("Dark")
}
.pickerStyle(SegmentedPickerStyle())
}
}
.navigationTitle("Settings")
}
}
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
SettingsView()
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
//
// ShareButton.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct ShareButton: View {
let image: UIImage
@State private var isShowingShareSheet = false
var body: some View {
Button("Share") {
isShowingShareSheet = true
}
.sheet(isPresented: $isShowingShareSheet) {
ShareSheet(activityItems: [image])
}
}
}
/// A UIViewControllerRepresentable that presents the iOS Share Sheet
struct ShareSheet: UIViewControllerRepresentable {
let activityItems: [Any]
func makeUIViewController(context: Context) -> UIActivityViewController {
UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) { }
}
import SwiftUI
import SwiftData
struct StickyNoteDetailView: View {
@Environment(\.modelContext) private var modelContext
let note: StickyNote
var body: some View {
ScrollView {
VStack(spacing: 16) {
if let imageData = note.imageData, let uiImage = UIImage(data: imageData) {
Image(uiImage: uiImage)
.resizable()
.scaledToFit()
.cornerRadius(10)
.padding()
}
if let text = note.textContent {
Text(text)
.font(.title3)
.multilineTextAlignment(.leading)
.padding(.horizontal)
}
Text(note.dateCreated, style: .date)
.font(.footnote)
.foregroundColor(.secondary)
// Optionally, include controls to mark complete or delete
Toggle("Mark Completed", isOn: bindingForIsCompleted)
.padding(.horizontal)
Button(role: .destructive) {
modelContext.delete(note)
} label: {
Text("Delete Sticky Note")
}
.padding()
}
}
.navigationTitle("Note Detail")
.navigationBarTitleDisplayMode(.inline)
}
private var bindingForIsCompleted: Binding<Bool> {
Binding(
get: { note.isCompleted },
set: { note.isCompleted = $0 }
)
}
}
//
// StickyNoteGalleryView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
import SwiftData
struct StickyNoteGalleryView: View {
@Query private var stickyNotes: [StickyNote]
var body: some View {
List {
ForEach(stickyNotes) { note in
NavigationLink(destination: StickyNoteDetailView(note: note)) {
HStack {
if let data = note.imageData,
let uiImage = UIImage(data: data) {
Image(uiImage: uiImage)
.resizable()
.scaledToFit()
.frame(width: 60, height: 60)
.cornerRadius(8)
}
VStack(alignment: .leading) {
if let text = note.textContent {
Text(text)
.font(.headline)
.lineLimit(1)
}
Text(note.dateCreated, style: .date)
.font(.caption)
.foregroundColor(.secondary)
if note.isCompleted {
Text("Completed")
.font(.caption2)
.foregroundColor(.green)
}
}
Spacer()
}
}
}
}
.navigationTitle("Sticky Notes")
}
}
import SwiftUI
import SwiftData
struct StickyNoteGridView: View {
let stickyNotes: [StickyNote]
var onSelect: (StickyNote) -> Void // Called when a note is tapped
@Environment(\.modelContext) private var modelContext
let columns = [
GridItem(.flexible(), spacing: 16),
GridItem(.flexible(), spacing: 16)
]
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 16) {
ForEach(stickyNotes) { note in
StickyNoteCell(note: note)
.onTapGesture {
onSelect(note)
}
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 3)
.swipeActions {
Button(role: .destructive) {
modelContext.delete(note)
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
.padding()
}
}
}
struct StickyNoteCell: View {
let note: StickyNote
var body: some View {
VStack {
if let imageData = note.imageData, let uiImage = UIImage(data: imageData) {
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
.frame(height: 120)
.clipped()
} else {
Rectangle()
.fill(Color.gray.opacity(0.3))
.frame(height: 120)
}
if let text = note.textContent {
Text(text)
.font(.headline)
.lineLimit(2)
.padding([.leading, .trailing, .bottom], 8)
}
}
}
}
import SwiftUI
import SwiftData
struct StickyNotesTabView: View {
@Query private var stickyNotes: [StickyNote]
@Environment(\.modelContext) private var modelContext
@State private var showNotepadSheet: Bool = false
@State private var selectedStickyNote: StickyNote? = nil
var body: some View {
NavigationStack {
ZStack(alignment: .bottomTrailing) {
// Pass in a closure to handle selection
StickyNoteGridView(stickyNotes: stickyNotes, onSelect: { note in
selectedStickyNote = note
})
// Floating button to add a sticky note
Button(action: {
showNotepadSheet.toggle()
}) {
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 60, height: 60)
.foregroundColor(.blue)
.shadow(radius: 5)
.padding()
}
}
.navigationTitle("Sticky Notes")
// Full-screen cover for adding a new sticky note
.fullScreenCover(isPresented: $showNotepadSheet) {
FullScreenNotepadView()
}
// Full-screen cover for viewing a sticky note detail
.fullScreenCover(item: $selectedStickyNote) { note in
StickyNoteDetailView(note: note)
}
}
}
}
//
// StickyNoteView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
import PencilKit
import SwiftData
struct StickyNoteView: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.modelContext) private var modelContext
@State private var canvasView = PKCanvasView()
@State private var textContent: String = ""
@State private var selectedColor: Color = .black
@State private var selectedWidth: CGFloat = 3
@State private var tool: PKTool = PKInkingTool(.pen, color: .black, width: 3)
var body: some View {
VStack(spacing: 10) {
Text("New Sticky Note")
.font(.title2)
.fontWeight(.bold)
TextField("Enter note text...", text: $textContent)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
PencilCanvasView(canvasView: $canvasView, tool: $tool)
.frame(height: 300)
.background(Color.white)
.cornerRadius(15)
.shadow(radius: 5)
toolSelectionControls()
HStack {
Button("Save") {
saveStickyNote()
dismiss()
}
.buttonStyle(.borderedProminent)
Button("Clear") {
clearCanvas()
}
.buttonStyle(.bordered)
.tint(.red)
Button("Close") {
dismiss()
}
.buttonStyle(.bordered)
}
.padding()
}
.padding()
.background(Color.white)
}
private func saveStickyNote() {
let imageData = canvasView.drawing.dataRepresentation()
let note = StickyNote(
textContent: textContent,
imageData: imageData,
dateCreated: Date(),
isCompleted: false
)
modelContext.insert(note)
}
private func clearCanvas() {
canvasView.drawing = PKDrawing()
}
private func toolSelectionControls() -> some View {
HStack {
// Tool selection controls (e.g., color picker and width slider)
ColorPicker("Color", selection: $selectedColor)
.onChange(of: selectedColor) { newValue in
tool = PKInkingTool(.pen, color: UIColor(newValue), width: selectedWidth)
}
Slider(value: $selectedWidth, in: 1...10, step: 1)
.onChange(of: selectedWidth) { newValue in
tool = PKInkingTool(.pen, color: UIColor(selectedColor), width: newValue)
}
}
.padding()
}
}
//
// TodoCardView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct TodoCardView: View {
let task: TodoItem
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 8) {
Text(task.title)
.font(.headline)
Text(task.isRecurring ? "Every Day" : "One-Time")
.font(.subheadline)
.foregroundColor(.secondary)
}
Spacer()
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
.foregroundColor(task.isCompleted ? .green : .gray)
}
.padding()
.background(Color(UIColor.secondarySystemBackground))
.cornerRadius(10)
}
}
import SwiftUI
struct TodoDetailView: View {
@State var task: TodoItem
@ObservedObject var todoViewModel: TodoViewModel
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
Form {
Section(header: Text("Task Title")) {
TextField("Title", text: $task.title)
}
Section(header: Text("Task Type")) {
Picker("Task Type", selection: $task.isRecurring) {
Text("One-Time").tag(false)
Text("Every Day").tag(true)
}
.pickerStyle(SegmentedPickerStyle())
}
Section {
Toggle("Completed", isOn: $task.isCompleted)
}
}
.navigationTitle("Edit Task")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
todoViewModel.updateTodo(todo: task, title: task.title, isRecurring: task.isRecurring)
dismiss()
}
}
}
}
}
}
//
// TodoListView.swift
// JacobsWorkApp
//
// Created by Jacob Spence on 2/7/25.
//
import SwiftUI
struct TodoListView: View {
@EnvironmentObject var todoViewModel: TodoViewModel
@State private var newTodoTitle: String = ""
var body: some View {
VStack {
List {
ForEach(todoViewModel.todos) { todo in
HStack {
Button(action: {
todoViewModel.toggleTodoCompletion(todo: todo)
}) {
Image(systemName: todo.isCompleted ? "checkmark.circle.fill" : "circle")
}
Text(todo.title)
.strikethrough(todo.isCompleted, color: .gray)
}
}
}
HStack {
TextField("New Todo", text: $newTodoTitle)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("Add") {
guard !newTodoTitle.isEmpty else { return }
todoViewModel.addTodo(title: newTodoTitle)
newTodoTitle = ""
}
}
.padding()
}
.navigationTitle("Todos")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment