Initial commit: KisaniCal iOS app

Task management, Eisenhower matrix, workout logging with persistence,
and calendar with 6 view modes (Month, List, Year, Week, 3 Day, Day).
Custom floating tab bar, dynamic calendar icon, and workout data seeded.
This commit is contained in:
kutesir
2026-05-27 02:09:44 +03:00
commit f67429de0b
22 changed files with 6797 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
import SwiftUI
// MARK: - Accent & Semantic Colors
struct AppColors {
// Fixed accent palette
static let accent = Color(r: 232, g: 98, b: 42)
static let green = Color(r: 62, g: 207, b: 142)
static let blue = Color(r: 77, g: 157, b: 224)
static let yellow = Color(r: 232, g: 184, b: 42)
static let red = Color(r: 232, g: 66, b: 66)
static let accentSoft = Color(UIColor { $0.userInterfaceStyle == .dark
? UIColor(r: 52, g: 28, b: 14) // dark: deep warm orange
: UIColor(r: 252, g: 238, b: 228) })// light: warm peach wash
static let accentGhost = accent.opacity(0.05)
static let greenSoft = Color(UIColor { $0.userInterfaceStyle == .dark
? UIColor(r: 14, g: 40, b: 28)
: UIColor(r: 220, g: 248, b: 236) })
static let blueSoft = Color(UIColor { $0.userInterfaceStyle == .dark
? UIColor(r: 14, g: 30, b: 50)
: UIColor(r: 222, g: 237, b: 252) })
static let yellowSoft = Color(UIColor { $0.userInterfaceStyle == .dark
? UIColor(r: 44, g: 34, b: 10)
: UIColor(r: 252, g: 243, b: 215) })
static let redSoft = Color(UIColor { $0.userInterfaceStyle == .dark
? UIColor(r: 50, g: 14, b: 14)
: UIColor(r: 252, g: 224, b: 224) })
// Adaptive surfaces
static func background(_ cs: ColorScheme) -> Color {
cs == .dark ? Color(r: 9, g: 9, b: 9)
: Color(r: 245, g: 243, b: 240)
}
static func surface(_ cs: ColorScheme) -> Color {
cs == .dark ? Color(r: 19, g: 19, b: 19)
: Color(r: 255, g: 253, b: 250) // warm white, not clinical pure white
}
static func surface2(_ cs: ColorScheme) -> Color {
cs == .dark ? Color(r: 26, g: 26, b: 26)
: Color(r: 240, g: 237, b: 232)
}
static func surface3(_ cs: ColorScheme) -> Color {
cs == .dark ? Color(r: 34, g: 34, b: 34)
: Color(r: 232, g: 228, b: 222)
}
static func text(_ cs: ColorScheme) -> Color {
cs == .dark ? Color(r: 240, g: 237, b: 232)
: Color(r: 26, g: 23, b: 20)
}
static func text2(_ cs: ColorScheme) -> Color {
text(cs).opacity(cs == .dark ? 0.44 : 0.50)
}
static func text3(_ cs: ColorScheme) -> Color {
text(cs).opacity(cs == .dark ? 0.24 : 0.34)
}
static func border(_ cs: ColorScheme) -> Color {
cs == .dark ? Color.white.opacity(0.07)
: Color.black.opacity(0.09)
}
static func borderHi(_ cs: ColorScheme) -> Color {
cs == .dark ? Color.white.opacity(0.13)
: Color.black.opacity(0.17)
}
static func phoneSheetBg(_ cs: ColorScheme) -> Color {
cs == .dark ? Color(r: 18, g: 18, b: 18)
: Color.white
}
}
private extension Color {
init(r: Double, g: Double, b: Double) {
self.init(.sRGB, red: r / 255, green: g / 255, blue: b / 255)
}
}
private extension UIColor {
convenience init(r: Int, g: Int, b: Int) {
self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: 1)
}
}
// MARK: - Typography
struct AppFonts {
static func sans(_ size: CGFloat, weight: Font.Weight = .regular) -> Font {
.system(size: size, weight: weight, design: .default)
}
static func mono(_ size: CGFloat, weight: Font.Weight = .regular) -> Font {
.system(size: size, weight: weight, design: .monospaced)
}
}
// MARK: - Motion Tokens
enum KisaniSpring {
/// General entrance slight overshoot, feels alive ( 320ms settle)
static let entrance = Animation.spring(response: 0.38, dampingFraction: 0.72)
/// Exit snappier, ~20% shorter settle than entrance
static let exit = Animation.spring(response: 0.28, dampingFraction: 0.88)
/// Micro-interactions button presses, toggles, chips (< 150ms feel)
static let micro = Animation.spring(response: 0.22, dampingFraction: 0.70)
/// Snappy section expands, panel slides ( 250ms settle)
static let snappy = Animation.spring(response: 0.32, dampingFraction: 0.78)
/// Bouncy checkmarks, completion states noticeable overshoot
static let bounce = Animation.spring(response: 0.28, dampingFraction: 0.52)
}
// MARK: - Corner Radii
enum AppRadius {
static let large: CGFloat = 16
static let medium: CGFloat = 13
static let small: CGFloat = 10
static let pill: CGFloat = 20
}
// MARK: - Icon color helpers
extension Int {
var iconColor: Color {
[AppColors.accent, AppColors.blue, AppColors.green, AppColors.yellow][self % 4]
}
var iconBg: Color {
[AppColors.accentSoft, AppColors.blueSoft, AppColors.greenSoft, AppColors.yellowSoft][self % 4]
}
}