Skip to content

Instantly share code, notes, and snippets.

@Shubham0812
Last active November 15, 2024 18:55
Show Gist options
  • Save Shubham0812/91341b888067548bd5cc4784799e9bf8 to your computer and use it in GitHub Desktop.
Save Shubham0812/91341b888067548bd5cc4784799e9bf8 to your computer and use it in GitHub Desktop.
TaskListView
//
// TaskListView.swift
// ToDo_UI
//
// Created by Shubham on 13/11/24.
//
import SwiftUI
struct TaskListView: View {
// MARK: - Variables
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest var fetchRequest: FetchedResults<Task>
@State var viewAppeared: Bool = false
var width: CGFloat
var completionPercentage: Double {
let completedTasks = fetchRequest.filter { $0.completed }.count
let totalTasks = fetchRequest.count
return totalTasks > 0 ? (Double(completedTasks) / Double(totalTasks)) : 0
}
// MARK: - Inits
init(selectedDate: Date, width: CGFloat) {
let startOfDay = Calendar.current.startOfDay(for: selectedDate)
let endOfDay = Calendar.current.date(byAdding: .day, value: 1, to: startOfDay) ?? selectedDate
// Create the predicate
let predicate = NSPredicate(format: "date >= %@ AND date < %@", startOfDay as NSDate, endOfDay as NSDate)
// Initialize the @FetchRequest with the predicate and sort descriptors
_fetchRequest = FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Task.date, ascending: true)],
predicate: predicate,
animation: .smooth(duration: 0.5)
)
self.width = width
}
// MARK: - Views
var body: some View {
VStack(alignment: .leading) {
VStack(alignment: .leading) {
HStack {
Text("Progress")
.font(Montserrat.medium.font(size: 20))
.textCase(.uppercase)
.opacity(0.75)
Spacer()
Text("\((completionPercentage * 100).clean(places: 1))%")
.font(Montserrat.bold.font(size: 28))
.contentTransition(.numericText())
.animation(.smooth, value: completionPercentage)
}
.padding(.top, 12)
GenerateProgressView()
.frame(height: 10)
.padding(.top, 4)
}
.offset(y: viewAppeared ? 0 : -16)
.opacity(viewAppeared ? 1 : 0)
.animation(.smooth.delay(0.15), value: viewAppeared)
HStack {
Text("Your Tasks")
.font(Nocturne.semibold.font(size: 28))
Spacer()
Image(systemName: "hand.thumbsup.fill")
.foregroundStyle(.yellow)
.font(.system(size: 28, weight: .semibold))
.opacity(completionPercentage == 1 ? 1 : 0)
.symbolEffect(.wiggle.byLayer, value: completionPercentage == 1)
.animation(.smooth, value: completionPercentage)
}
.padding(.top, 32)
.offset(y: viewAppeared ? 0 : -16)
.opacity(viewAppeared ? 1 : 0)
.animation(.smooth.delay(0.175), value: viewAppeared)
VStack(alignment: .leading, spacing: 14) {
ForEach(Array(zip(fetchRequest.indices, fetchRequest)), id: \.1.id) { ix, task in
TaskRowView(task: task)
.frame(height: 56)
.opacity(self.viewAppeared ? 1 : 0)
.offset(y: self.viewAppeared ? 0 : 45 * Double(ix + 1))
.animation(.smooth(duration: 0.35).delay(0.15).delay(0.1 * Double(ix + 1)), value: self.viewAppeared)
}
}
.padding(.top, 12)
}
.onAppear() {
viewAppeared.toggle()
}
}
// MARK: - Functions
@ViewBuilder
func GenerateProgressView() -> some View {
ZStack(alignment: Alignment(horizontal: .leading, vertical: .top)) {
ZStack {
RoundedRectangle(cornerRadius: 12)
.offset(x: 0, y: 3)
RoundedRectangle(cornerRadius: 12)
.foregroundColor(Color.background)
RoundedRectangle(cornerRadius: 12)
.stroke(style: StrokeStyle(lineWidth: 1.5, lineCap: .round, lineJoin: .round))
}
RoundedRectangle(cornerRadius: 12)
.foregroundColor(.label.opacity(0.35))
.shadow(color: .label.opacity(0.015), radius: 5)
RoundedRectangle(cornerRadius: 12)
.frame(width: width * completionPercentage, alignment: .leading)
.foregroundColor(.green)
}
}
}
#Preview {
TaskListView(selectedDate: Date(), width: UIScreen.main.bounds.width)
.padding(24)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment