UI updates for labwise branding

This commit is contained in:
2026-03-20 02:05:53 -05:00
parent 12a79db143
commit efec14139c
23 changed files with 705 additions and 28 deletions

8
LabWiseKit/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

26
LabWiseKit/Package.swift Normal file
View File

@@ -0,0 +1,26 @@
// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "LabWiseKit",
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "LabWiseKit",
targets: ["LabWiseKit"]
),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "LabWiseKit"
),
.testTarget(
name: "LabWiseKitTests",
dependencies: ["LabWiseKit"]
),
]
)

View File

@@ -0,0 +1,2 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book

View File

@@ -0,0 +1,164 @@
import Foundation
public struct Chemical: Codable, Identifiable, Sendable {
public let id: String
// Required
public var piFirstName: String
public var physicalState: String
public var chemicalName: String
public var bldgCode: String
public var lab: String
public var storageLocation: String
public var storageDevice: String
public var numberOfContainers: String
public var amountPerContainer: String
public var unitOfMeasure: String
public var casNumber: String
// Optional
public var chemicalFormula: String?
public var molecularWeight: String?
public var vendor: String?
public var catalogNumber: String?
public var lotNumber: String?
public var expirationDate: String?
public var concentration: String?
public var percentageFull: Double?
public var comments: String?
public var barcode: String?
public var contact: String?
public var scannedImage: String?
public var needsManualEntry: [String]?
public var createdAt: String?
public var updatedAt: String?
public init(
id: String = "",
piFirstName: String = "",
physicalState: String = "",
chemicalName: String = "",
bldgCode: String = "",
lab: String = "",
storageLocation: String = "",
storageDevice: String = "",
numberOfContainers: String = "",
amountPerContainer: String = "",
unitOfMeasure: String = "",
casNumber: String = "",
chemicalFormula: String? = nil,
molecularWeight: String? = nil,
vendor: String? = nil,
catalogNumber: String? = nil,
lotNumber: String? = nil,
expirationDate: String? = nil,
concentration: String? = nil,
percentageFull: Double? = nil,
comments: String? = nil,
barcode: String? = nil,
contact: String? = nil,
scannedImage: String? = nil,
needsManualEntry: [String]? = nil,
createdAt: String? = nil,
updatedAt: String? = nil
) {
self.id = id
self.piFirstName = piFirstName
self.physicalState = physicalState
self.chemicalName = chemicalName
self.bldgCode = bldgCode
self.lab = lab
self.storageLocation = storageLocation
self.storageDevice = storageDevice
self.numberOfContainers = numberOfContainers
self.amountPerContainer = amountPerContainer
self.unitOfMeasure = unitOfMeasure
self.casNumber = casNumber
self.chemicalFormula = chemicalFormula
self.molecularWeight = molecularWeight
self.vendor = vendor
self.catalogNumber = catalogNumber
self.lotNumber = lotNumber
self.expirationDate = expirationDate
self.concentration = concentration
self.percentageFull = percentageFull
self.comments = comments
self.barcode = barcode
self.contact = contact
self.scannedImage = scannedImage
self.needsManualEntry = needsManualEntry
self.createdAt = createdAt
self.updatedAt = updatedAt
}
}
public struct ChemicalCreateBody: Codable, Sendable {
public var piFirstName: String
public var physicalState: String
public var chemicalName: String
public var bldgCode: String
public var lab: String
public var storageLocation: String
public var storageDevice: String
public var numberOfContainers: String
public var amountPerContainer: String
public var unitOfMeasure: String
public var casNumber: String
public var chemicalFormula: String?
public var molecularWeight: String?
public var vendor: String?
public var catalogNumber: String?
public var lotNumber: String?
public var expirationDate: String?
public var concentration: String?
public var percentageFull: Double?
public var comments: String?
public var barcode: String?
public var contact: String?
public init(
piFirstName: String,
physicalState: String,
chemicalName: String,
bldgCode: String,
lab: String,
storageLocation: String,
storageDevice: String,
numberOfContainers: String,
amountPerContainer: String,
unitOfMeasure: String,
casNumber: String,
chemicalFormula: String? = nil,
molecularWeight: String? = nil,
vendor: String? = nil,
catalogNumber: String? = nil,
lotNumber: String? = nil,
expirationDate: String? = nil,
concentration: String? = nil,
percentageFull: Double? = nil,
comments: String? = nil,
barcode: String? = nil,
contact: String? = nil
) {
self.piFirstName = piFirstName
self.physicalState = physicalState
self.chemicalName = chemicalName
self.bldgCode = bldgCode
self.lab = lab
self.storageLocation = storageLocation
self.storageDevice = storageDevice
self.numberOfContainers = numberOfContainers
self.amountPerContainer = amountPerContainer
self.unitOfMeasure = unitOfMeasure
self.casNumber = casNumber
self.chemicalFormula = chemicalFormula
self.molecularWeight = molecularWeight
self.vendor = vendor
self.catalogNumber = catalogNumber
self.lotNumber = lotNumber
self.expirationDate = expirationDate
self.concentration = concentration
self.percentageFull = percentageFull
self.comments = comments
self.barcode = barcode
self.contact = contact
}
}

View File

@@ -0,0 +1,83 @@
import Foundation
/// A lab protocol document. Named `LabProtocol` to avoid collision with the Swift keyword `Protocol`.
public struct LabProtocol: Codable, Identifiable, Sendable {
public let id: String
public var title: String
public var content: String
public var fileUrl: String?
public var analysisResults: AnyCodable?
public var createdAt: String?
public var updatedAt: String?
enum CodingKeys: String, CodingKey {
case id, title, content, fileUrl, analysisResults, createdAt, updatedAt
}
public init(
id: String = "",
title: String = "",
content: String = "",
fileUrl: String? = nil,
analysisResults: AnyCodable? = nil,
createdAt: String? = nil,
updatedAt: String? = nil
) {
self.id = id
self.title = title
self.content = content
self.fileUrl = fileUrl
self.analysisResults = analysisResults
self.createdAt = createdAt
self.updatedAt = updatedAt
}
}
// MARK: - AnyCodable helper
public struct AnyCodable: Codable, Sendable {
public let value: any Sendable
public init(_ value: any Sendable) {
self.value = value
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let intVal = try? container.decode(Int.self) {
value = intVal
} else if let doubleVal = try? container.decode(Double.self) {
value = doubleVal
} else if let boolVal = try? container.decode(Bool.self) {
value = boolVal
} else if let stringVal = try? container.decode(String.self) {
value = stringVal
} else if let arrayVal = try? container.decode([AnyCodable].self) {
value = arrayVal
} else if let dictVal = try? container.decode([String: AnyCodable].self) {
value = dictVal
} else {
value = NSNull()
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch value {
case let intVal as Int:
try container.encode(intVal)
case let doubleVal as Double:
try container.encode(doubleVal)
case let boolVal as Bool:
try container.encode(boolVal)
case let stringVal as String:
try container.encode(stringVal)
case let arrayVal as [AnyCodable]:
try container.encode(arrayVal)
case let dictVal as [String: AnyCodable]:
try container.encode(dictVal)
default:
try container.encodeNil()
}
}
}

View File

@@ -0,0 +1,6 @@
import Testing
@testable import LabWiseKit
@Test func example() async throws {
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
}