add fixture-backed admin and ios scaffold

This commit is contained in:
2026-04-09 15:30:00 +02:00
parent a1dcebaec1
commit 87f152a232
33 changed files with 927 additions and 24 deletions
+10
View File
@@ -0,0 +1,10 @@
import SwiftUI
@main
struct HermesApp: App {
var body: some Scene {
WindowGroup {
RootView()
}
}
}
+18
View File
@@ -0,0 +1,18 @@
import SwiftUI
struct RootView: View {
var body: some View {
NavigationStack {
VStack(spacing: 16) {
Text("Hermes")
.font(.largeTitle.bold())
Text("Native study app scaffold")
.font(.body)
.foregroundStyle(.secondary)
OnboardingView()
}
.padding()
.navigationTitle("Hermes")
}
}
}
@@ -0,0 +1,13 @@
import Foundation
protocol AnalyticsTracking {
func track(_ event: String, attributes: [String: String])
}
final class HermesAnalyticsClient: AnalyticsTracking {
func track(_ event: String, attributes: [String: String]) {
// Scaffold implementation.
_ = event
_ = attributes
}
}
@@ -0,0 +1,9 @@
import SwiftUI
enum HermesTheme {
static let background = Color.black
static let surface = Color(red: 0.12, green: 0.12, blue: 0.14)
static let accent = Color(red: 0.87, green: 0.74, blue: 0.34)
static let textPrimary = Color.white
static let textSecondary = Color.white.opacity(0.72)
}
@@ -0,0 +1,6 @@
import Foundation
struct GestureHandlers {
func handleTap() {}
func handleSwipeDown() {}
}
@@ -0,0 +1,6 @@
import Foundation
final class HapticsController {
func selectionAccepted() {}
func marketLocked() {}
}
@@ -0,0 +1,18 @@
import Foundation
final class LocalizationStore {
private let bundle: Bundle
init(bundle: Bundle = .main) {
self.bundle = bundle
}
func string(for key: String, locale: String) -> String {
guard let path = bundle.path(forResource: locale, ofType: "lproj"),
let localizedBundle = Bundle(path: path) else {
return bundle.localizedString(forKey: key, value: nil, table: nil)
}
return localizedBundle.localizedString(forKey: key, value: nil, table: nil)
}
}
@@ -0,0 +1,6 @@
import Foundation
final class PlayerCoordinator: ObservableObject {
@Published var isPlaying = false
@Published var playbackPositionMs: Int = 0
}
@@ -0,0 +1,24 @@
import Foundation
struct APIEnvironment {
let baseURL: URL
}
struct HermesAPIClient {
let environment: APIEnvironment
let session: URLSession
init(environment: APIEnvironment, session: URLSession = .shared) {
self.environment = environment
self.session = session
}
func get(path: String) async throws -> (Data, HTTPURLResponse) {
let url = environment.baseURL.appendingPathComponent(path)
let (data, response) = try await session.data(from: url)
guard let httpResponse = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
return (data, httpResponse)
}
}
@@ -0,0 +1,15 @@
import SwiftUI
struct FeedView: View {
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Next round")
.font(.headline)
Text("A new clip is ready for review.")
.foregroundStyle(.secondary)
}
.padding()
.background(HermesTheme.surface)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
}
}
@@ -0,0 +1,18 @@
import SwiftUI
struct OnboardingView: View {
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Study intro")
.font(.headline)
Text("Watch the clip, make your choice before lock, then see the reveal.")
.foregroundStyle(.secondary)
Button("Start session") {}
.buttonStyle(.borderedProminent)
}
.padding()
.background(HermesTheme.surface)
.foregroundStyle(HermesTheme.textPrimary)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
}
}
@@ -0,0 +1,7 @@
import SwiftUI
struct ResultView: View {
var body: some View {
Text("Result scaffold")
}
}
@@ -0,0 +1,7 @@
import SwiftUI
struct RevealView: View {
var body: some View {
Text("Reveal scaffold")
}
}
@@ -0,0 +1,8 @@
import SwiftUI
struct RoundView: View {
var body: some View {
Text("Round scaffold")
.padding()
}
}
@@ -0,0 +1,7 @@
import SwiftUI
struct SelectionView: View {
var body: some View {
Text("Selection scaffold")
}
}
@@ -0,0 +1,7 @@
import SwiftUI
struct SessionView: View {
var body: some View {
Text("Session scaffold")
}
}
@@ -0,0 +1,7 @@
import SwiftUI
struct SettingsView: View {
var body: some View {
Text("Settings scaffold")
}
}
@@ -0,0 +1,4 @@
"app.name" = "Hermes";
"onboarding.title" = "Study intro";
"onboarding.start_session" = "Start session";
"feed.next_round_title" = "Next round";
@@ -0,0 +1,4 @@
"app.name" = "Hermes";
"onboarding.title" = "Studieintro";
"onboarding.start_session" = "Starta session";
"feed.next_round_title" = "Nästa runda";