diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8c44e1b..9116327 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.jetbrains.kotlin.android) + id("app.cash.sqldelight") } android { @@ -40,7 +41,7 @@ android { compose = true } composeOptions { - kotlinCompilerExtensionVersion = "1.5.1" + kotlinCompilerExtensionVersion = "1.5.13" } packaging { resources { @@ -56,8 +57,20 @@ android { } dependencies { + + // Versions + val sqlDelightVersion = "2.0.2" + val koinVersion = "4.0.0-RC1" + + // AndroidX Core Libraries implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.navigation.common.ktx) + implementation(libs.androidx.navigation.runtime.ktx) + + // AndroidX Compose Libraries implementation(libs.androidx.activity.compose) implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.ui) @@ -65,15 +78,39 @@ dependencies { implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) implementation(libs.androidx.window) - implementation(libs.androidx.appcompat) - implementation(libs.androidx.navigation.runtime.ktx) - implementation(libs.androidx.navigation.compose) - implementation(libs.androidx.navigation.common.ktx) + + //SQLDelight + implementation("app.cash.sqldelight:android-driver:$sqlDelightVersion") + implementation("app.cash.sqldelight:coroutines-extensions-jvm:$sqlDelightVersion") + implementation("app.cash.sqldelight:primitive-adapters:$sqlDelightVersion") + + // GSON + implementation("com.google.code.gson:gson:2.11.0") + + + // Koin for Android + implementation(platform("io.insert-koin:koin-bom:$koinVersion")) + implementation("io.insert-koin:koin-core") + implementation (libs.koin.android) + implementation("io.insert-koin:koin-androidx-compose:$koinVersion") + + // Testing testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) + + runtimeOnly("org.jetbrains.kotlin:kotlin-reflect:2.0.21-RC") } + +sqldelight { + databases { + create("MensinatorDB") { + packageName.set("com.mensinator.app.database") + } + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 323997b..71dabe9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,9 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/Theme.Mensinator" - tools:targetApi="31"> + tools:targetApi="31" + android:name=".MensinatorApplication" + > { + AndroidSqliteDriver( + schema = MensinatorDB.Schema, + context = get(), + name = "mensinator.db" + ) + } + + single { + MensinatorDB(get()) + } +} + +val dataModule = module { + single { AppSettingRepository(get()) } + viewModelOf(::AppSettingViewModel) + + single { CycleRepository(get()) } + viewModelOf(::CycleViewModel) + + single { NoteRepository(get()) } + viewModelOf(::NoteViewModel) + + single { OvulationRepository(get()) } + viewModelOf(::OvulationViewModel) + + single { PeriodRepository(get()) } + viewModelOf(::PeriodViewModel) + + single { PredictionRepository(get()) } + viewModelOf(::PredictionViewModel) +} diff --git a/app/src/main/java/com/mensinator/app/ExportImport.kt b/app/src/main/java/com/mensinator/app/ExportImport.kt index 3790e3d..0531b1c 100644 --- a/app/src/main/java/com/mensinator/app/ExportImport.kt +++ b/app/src/main/java/com/mensinator/app/ExportImport.kt @@ -7,18 +7,18 @@ import android.database.sqlite.SQLiteDatabase import android.icu.text.SimpleDateFormat import android.os.Environment import android.util.Log -import org.json.JSONObject +import com.mensinator.app.database.ImportExportManager import org.json.JSONArray +import org.json.JSONObject +import java.io.BufferedReader import java.io.File -import java.io.FileOutputStream import java.io.FileInputStream +import java.io.FileOutputStream import java.io.InputStreamReader -import java.io.BufferedReader import java.util.Date import java.util.Locale - class ExportImport { fun getDocumentsExportFilePath(): String { @@ -87,6 +87,9 @@ class ExportImport { fileOutputStream.close() db.close() + + // Export function - to implement it better + ImportExportManager().exportDatabase("/storage/self/primary/Documents/") } private fun cursorToJsonArray(cursor: Cursor): JSONArray { @@ -102,6 +105,8 @@ class ExportImport { } fun importDatabase(context: Context, filePath: String) { + ImportExportManager().importDatabase(filePath) + val dbHelper = PeriodDatabaseHelper(context) val db = dbHelper.writableDatabase @@ -157,6 +162,7 @@ class ExportImport { } db.close() + } // This function will delete all period, ovulation, symptoms and symptomdates before importing the file diff --git a/app/src/main/java/com/mensinator/app/MensinatorApplication.kt b/app/src/main/java/com/mensinator/app/MensinatorApplication.kt new file mode 100644 index 0000000..41a3513 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/MensinatorApplication.kt @@ -0,0 +1,19 @@ +package com.mensinator.app +import android.app.Application +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.core.context.startKoin + +class MensinatorApplication : Application() { + override fun onCreate() { + super.onCreate() + startKoin { + androidContext(this@MensinatorApplication) + androidLogger() + modules( + databaseModule, + dataModule + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/DatabaseEnums.kt b/app/src/main/java/com/mensinator/app/database/DatabaseEnums.kt new file mode 100644 index 0000000..8b5a59a --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/DatabaseEnums.kt @@ -0,0 +1,33 @@ +package com.mensinator.app.database + +enum class AppCategory(val value: String) { + COLORS("Colors"), + REMINDERS("Reminders"), + OTHERS("Other settings") +} + +enum class NoteCategory(val value: String){ + SYMPTOMS("Symptoms"), + MOODS("Moods"), + SEX("Sex") +} + +enum class PredictionType(val value: String){ + PERIOD("Period"), + OVULATION("Ovulation") +} + +enum class Colors(val value: String) { + RED("Red"), + LIGHT_GRAY("LightGray"), + DARK_GRAY("DarkGray"), + YELLOW("Yellow"), + BLUE("Blue"), + MAGENTA("Magenta") +} + +enum class PredefinedSymptoms(val value: String){ + HEAVY_FLOW("Heavy flow"), + MEDIUM_FLOW("Medium flow"), + LIGHT_FLOW("Light flow"), +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/ImportExportManager.kt b/app/src/main/java/com/mensinator/app/database/ImportExportManager.kt new file mode 100644 index 0000000..ab334ad --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/ImportExportManager.kt @@ -0,0 +1,194 @@ +package com.mensinator.app.database + +import com.google.gson.GsonBuilder +import com.google.gson.JsonSyntaxException +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import java.io.File + +class ImportExportManager: KoinComponent { + private val gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() + + private val database: MensinatorDB by inject() + + private fun writeJsonToFile(json: String, filePath: String) { + val file = File(filePath + "mensinator_export.json") + file.writeText(json) + } + + fun exportDatabase(filePath: String) { + val cycles = database.cycleQueries.getAllCycles().executeAsList() + .map { cycle -> + mapOf( + "start_date" to cycle.start_date, + "end_date" to cycle.end_date, + "length" to cycle.length, + "luteal_phase_length" to cycle.luteal_phase_length + ) + } + + val appSettings = database.appSettingQueries.getAllSettings().executeAsList() + .map { appSetting -> + mapOf( + "label" to appSetting.label, + "value" to appSetting.value_, + "category" to appSetting.category + ) + } + + val notes = database.noteQueries.getAllNotes().executeAsList() + .map { note -> + mapOf( + "name" to note.name, + "category" to note.category, + "is_active" to note.is_active + ) + } + + val ovulations = database.ovulationQueries.getAllOvulations().executeAsList() + .map { ovulation -> + mapOf( + "date" to ovulation.date, + "cycle_id" to ovulation.cycle_id + ) + } + + val periods = database.periodQueries.getAllPeriods().executeAsList() + .map { period -> + mapOf( + "date" to period.date, + "cycle_id" to period.cycle_id + ) + } + + val predictions = database.predictionQueries.getAllPredictions().executeAsList() + .map { prediction -> + mapOf( + "date" to prediction.date, + "type" to prediction.type, + "cycle_id" to prediction.cycle_id + ) + } + + val noteDates = database.noteDateQueries.getAllNoteDates().executeAsList() + .map { noteDate -> + mapOf( + "date" to noteDate.date + ) + } + + val noteDateCrossRefs = database.noteDateCrossRefQueries.getAllNoteDateCrossRefs().executeAsList() + .map { noteDateCrossRef -> + mapOf( + "note_id" to noteDateCrossRef.note_id, + "note_date_id" to noteDateCrossRef.note_date_id + ) + } + + val data = mapOf( + "cycles" to cycles, + "app_settings" to appSettings, + "notes" to notes, + "note_dates" to noteDates, + "note_date_cross_refs" to noteDateCrossRefs, + "ovulations" to ovulations, + "periods" to periods, + "predictions" to predictions + ) + + val json = gson.toJson(data) + writeJsonToFile(json, filePath) + } + + fun importDatabase(filePath: String) { + val file = File(filePath) + + require(file.exists()) + + val json = file.readText() + + try { + + val data: Map = gson.fromJson( + json, + com.google.gson.reflect.TypeToken.getParameterized(Map::class.java, String::class.java, Any::class.java).type + ) + + val cycles = data["cycles"] as? List> ?: emptyList() + cycles.forEach { cycle -> + database.cycleQueries.insertCycle( + start_date = cycle["start_date"] as String, + end_date = cycle["end_date"] as? String, + length = (cycle["length"] as? String)?.toLongOrNull() ?: 0L, + luteal_phase_length = (cycle["luteal_phase_length"] as? String)?.toLongOrNull() ?: 0L + ) + } + + val appSettings = data["app_settings"] as? List> ?: emptyList() + appSettings.forEach { appSetting -> + database.appSettingQueries.insertAppSetting( + label = appSetting["label"] as String, + value_ = appSetting["value"] as String, + category = appSetting["category"] as String + ) + } + + val notes = data["notes"] as? List> ?: emptyList() + notes.forEach { note -> + database.noteQueries.insertNote( + name = note["name"] as String, + category = note["category"] as String, + is_active = when (val active = note["is_active"]) { + is Boolean -> active + is String -> active.toBoolean() + else -> false + } + ) + } + + val ovulations = data["ovulations"] as? List> ?: emptyList() + ovulations.forEach { ovulation -> + database.ovulationQueries.insertOvulation( + date = ovulation["date"] as String, + cycle_id = (ovulation["cycle_id"] as? String)?.toLongOrNull() ?: 0L + ) + } + + val periods = data["periods"] as? List> ?: emptyList() + periods.forEach { period -> + database.periodQueries.insertPeriod( + date = period["date"] as String, + cycle_id = (period["cycle_id"] as? String)?.toLongOrNull() ?: 0L + ) + } + + val predictions = data["predictions"] as? List> ?: emptyList() + predictions.forEach { prediction -> + database.predictionQueries.insertPrediction( + date = prediction["date"] as String, + type = prediction["type"] as String, + cycle_id = (prediction["cycle_id"] as? String)?.toLongOrNull() ?: 0L + ) + } + + val noteDates = data["note_dates"] as? List> ?: emptyList() + noteDates.forEach { noteDate -> + database.noteDateQueries.insertNoteDate( + date = noteDate["date"] as String + ) + } + + val noteDateCrossRefs = data["note_date_cross_refs"] as? List> ?: emptyList() + noteDateCrossRefs.forEach { noteDateCrossRef -> + database.noteDateCrossRefQueries.insertNoteDateCrossRef( + note_id = (noteDateCrossRef["note_id"] as? String)?.toLongOrNull() ?: 0L, + note_date_id = (noteDateCrossRef["note_date_id"] as? String)?.toLongOrNull() ?: 0L + ) + } + + } catch (e: JsonSyntaxException) { + throw IllegalArgumentException("Failed to parse JSON: ${e.message}") + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/repositories/AppSettingRepository.kt b/app/src/main/java/com/mensinator/app/database/repositories/AppSettingRepository.kt new file mode 100644 index 0000000..c1bd45c --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/repositories/AppSettingRepository.kt @@ -0,0 +1,87 @@ +package com.mensinator.app.database.repositories + +import com.mensinator.app.database.MensinatorDB +import com.mensinator.app.database.App_setting +import com.mensinator.app.database.AppCategory +import com.mensinator.app.database.Colors +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + + + +class AppSettingRepository(private val database: MensinatorDB, private val dispatcher: CoroutineDispatcher = Dispatchers.IO) { + + init { + insertPredefinedSettings(); + } + + private fun insertPredefinedSettings(){ + if(database.appSettingQueries.getAllSettings().executeAsList().isEmpty()){ + //Color settings + database.appSettingQueries.insertAppSetting("period_color", Colors.RED.value, AppCategory.COLORS.value) + database.appSettingQueries.insertAppSetting("selection_color", Colors.LIGHT_GRAY.value, AppCategory.COLORS.value) + database.appSettingQueries.insertAppSetting("period_selection_color", Colors.DARK_GRAY.value, AppCategory.COLORS.value) + database.appSettingQueries.insertAppSetting("expected_period_color", Colors.YELLOW.value, AppCategory.COLORS.value) + database.appSettingQueries.insertAppSetting("ovulation_color", Colors.BLUE.value, AppCategory.COLORS.value) + database.appSettingQueries.insertAppSetting("expected_ovulation_color", Colors.MAGENTA.value, AppCategory.COLORS.value) + + //Reminder settings + database.appSettingQueries.insertAppSetting("reminder_days", "0", AppCategory.REMINDERS.value) + + //Other settings + database.appSettingQueries.insertAppSetting("luteal_period_calculation", "0", AppCategory.OTHERS.value) + database.appSettingQueries.insertAppSetting("period_history", "5", AppCategory.OTHERS.value) + database.appSettingQueries.insertAppSetting("ovulation_history", "5", AppCategory.OTHERS.value) + database.appSettingQueries.insertAppSetting("language", "en", AppCategory.OTHERS.value) + database.appSettingQueries.insertAppSetting("cycle_numbers_show", "1", AppCategory.OTHERS.value) + } + } + + //----- READ ----- + + suspend fun getAllSettings(): List { + return withContext(dispatcher){ + database.appSettingQueries.getAllSettings().executeAsList() + } + } + + suspend fun getAllSettingsByCategory(category: String): List { + return withContext(dispatcher){ + database.appSettingQueries.getAllSettingsByCategory(category).executeAsList() + } + } + + + //----- CREATE ----- + + suspend fun insertAppSetting(label: String, value: String, category: String){ + withContext(dispatcher){ + database.appSettingQueries.insertAppSetting(label, value, category) + } + } + + + //----- UPDATE ----- + + suspend fun setAppSettingValue(value: String, label: String){ + withContext(dispatcher){ + database.appSettingQueries.setAppSettingValue(value, label) + } + } + + + //----- DELETE ----- + + suspend fun deleteAppSettingByLabel(label: String){ + withContext(dispatcher){ + database.appSettingQueries.deleteAppSettingByLabel(label) + } + } + + suspend fun deleteAppSettingsByCategory(category: String){ + withContext(dispatcher){ + database.appSettingQueries.deleteAppSettingsByCategory(category) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/repositories/CycleRepository.kt b/app/src/main/java/com/mensinator/app/database/repositories/CycleRepository.kt new file mode 100644 index 0000000..144f728 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/repositories/CycleRepository.kt @@ -0,0 +1,75 @@ +package com.mensinator.app.database.repositories + +import com.mensinator.app.database.Cycle +import com.mensinator.app.database.MensinatorDB +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class CycleRepository(private val database: MensinatorDB, private val dispatcher: CoroutineDispatcher = Dispatchers.IO) { + + //----- READ ----- + + suspend fun getAllCycles(): List { + return withContext(dispatcher){ + database.cycleQueries.getAllCycles().executeAsList() + } + } + + suspend fun getAllCyclesByInterval(startDate: String, endDate: String): List { + return withContext(dispatcher){ + database.cycleQueries.getAllCyclesByInterval(startDate, endDate).executeAsList() + } + } + + + //----- CREATE ----- + + suspend fun insertCycle(startDate: String, endDate: String, length: Long, lutealPhaseLength: Long) { + withContext(dispatcher){ + database.cycleQueries.insertCycle(startDate, endDate, length, lutealPhaseLength) + } + } + + suspend fun insertCycleByStartDate(startDate: String){ + withContext(dispatcher){ + database.cycleQueries.insertCycleByStartDate(startDate) + } + } + + + //----- UPDATE ----- + + suspend fun setCycleEndDate(endDate: String, id: Long){ + withContext(dispatcher){ + database.cycleQueries.setCycleEndDate(endDate, id) + } + } + + suspend fun setCycleLength(length: Long, id: Long){ + withContext(dispatcher){ + database.cycleQueries.setCycleLength(length, id) + } + } + + suspend fun setCycleLutealLength(lutealPhaseLength: Long, id: Long){ + withContext(dispatcher){ + database.cycleQueries.setCycleLutealLength(lutealPhaseLength, id) + } + } + + + //----- DELETE ----- + + suspend fun deleteCycleById(id: Long){ + withContext(dispatcher) { + database.cycleQueries.deleteCycleById(id) + } + } + + suspend fun deleteCycleByStartDate(startDate: String){ + withContext(dispatcher) { + database.cycleQueries.deleteCycleByStartDate(startDate) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/repositories/NoteRepository.kt b/app/src/main/java/com/mensinator/app/database/repositories/NoteRepository.kt new file mode 100644 index 0000000..e648069 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/repositories/NoteRepository.kt @@ -0,0 +1,109 @@ +package com.mensinator.app.database.repositories + +import com.mensinator.app.database.MensinatorDB +import com.mensinator.app.database.Note +import com.mensinator.app.database.NoteCategory +import com.mensinator.app.database.Note_date +import com.mensinator.app.database.PredefinedSymptoms +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class NoteRepository(private val database: MensinatorDB, private val dispatcher: CoroutineDispatcher = Dispatchers.IO) { + + init { + insertPredefinedNotes(); + } + + private fun insertPredefinedNotes(){ + if(database.noteQueries.getAllNotes().executeAsList().isEmpty()){ + //Type of flow + database.noteQueries.insertNote(PredefinedSymptoms.HEAVY_FLOW.value, NoteCategory.SYMPTOMS.value, true) + database.noteQueries.insertNote(PredefinedSymptoms.MEDIUM_FLOW.value, NoteCategory.SYMPTOMS.value, true) + database.noteQueries.insertNote(PredefinedSymptoms.LIGHT_FLOW.value, NoteCategory.SYMPTOMS.value, true) + } + } + + //----- READ ----- + + suspend fun getAllNotes(): List{ + return withContext(dispatcher){ + database.noteQueries.getAllNotes().executeAsList() + } + } + + suspend fun getAllNotesByCategory(category: String): List{ + return withContext(dispatcher){ + database.noteQueries.getAllNotesByCategory(category).executeAsList() + } + } + + suspend fun getAllNotesByDate(date: String): List{ + return withContext(dispatcher){ + database.noteQueries.getAllNotesByDate(date).executeAsList() + } + } + + suspend fun getAllDatesByNote(name: String): List{ + return withContext(dispatcher) { + database.noteDateQueries.getAllDatesByNote(name).executeAsList() + } + } + + + //----- CREATE ----- + + suspend fun insertNote(name: String, category: String, isActive: Boolean){ + withContext(dispatcher){ + database.noteQueries.insertNote(name, category, isActive) + } + } + + suspend fun insertNoteDate(date: String){ + withContext(dispatcher){ + database.noteDateQueries.insertNoteDate(date) + } + } + + suspend fun insertNoteDateCrossRef(noteId: Long, noteDateId: Long){ + withContext(dispatcher){ + database.noteDateCrossRefQueries.insertNoteDateCrossRef(noteId, noteDateId) + } + } + + + //----- UPDATE ----- + + suspend fun toggleNoteActiveStatus(name: String){ + withContext(dispatcher){ + database.noteQueries.toggleNoteActiveStatus(name) + } + } + + + //----- DELETE ----- + + suspend fun deleteNoteByName(name: String){ + withContext(dispatcher){ + database.noteQueries.deleteNoteByName(name) + } + } + + suspend fun deleteNotesByCategory(category: String){ + withContext(dispatcher){ + database.noteQueries.deleteNotesByCategory(category) + } + } + + suspend fun deleteNoteDate(date: String){ + withContext(dispatcher){ + database.noteDateQueries.deleteNoteDate(date) + } + } + + suspend fun deleteNoteDateCrossRef(noteId: Long, noteDateId: Long){ + withContext(dispatcher){ + database.noteDateCrossRefQueries.deleteNoteDateCrossRef(noteId, noteDateId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/repositories/OvulationRepository.kt b/app/src/main/java/com/mensinator/app/database/repositories/OvulationRepository.kt new file mode 100644 index 0000000..fa5f5b6 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/repositories/OvulationRepository.kt @@ -0,0 +1,57 @@ +package com.mensinator.app.database.repositories + +import com.mensinator.app.database.MensinatorDB +import com.mensinator.app.database.Ovulation +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class OvulationRepository(private val database: MensinatorDB, private val dispatcher: CoroutineDispatcher = Dispatchers.IO) { + + //----- READ ----- + + suspend fun getAllOvulations(): List { + return withContext(dispatcher){ + database.ovulationQueries.getAllOvulations().executeAsList() + } + } + + suspend fun getOvulationByDate(date: String): Ovulation? { + return withContext(dispatcher){ + database.ovulationQueries.getOvulationByDate(date).executeAsOneOrNull() + } + } + + suspend fun getOvulationByCycle(cycleId: Long): Ovulation? { + return withContext(dispatcher){ + database.ovulationQueries.getOvulationByCycle(cycleId).executeAsOneOrNull() + } + } + + + //----- CREATE ----- + + suspend fun insertOvulation(date: String, cycleId: Long){ + withContext(dispatcher){ + database.ovulationQueries.insertOvulation(date, cycleId) + } + } + + + //----- UPDATE ----- + + + //----- DELETE ----- + + suspend fun deleteOvulationByDate(date: String){ + withContext(dispatcher){ + database.ovulationQueries.deleteOvulationByDate(date) + } + } + + suspend fun deleteOvulationByCycle(cycleId: Long){ + withContext(dispatcher){ + database.ovulationQueries.deleteOvulationByCycle(cycleId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/repositories/PeriodRepository.kt b/app/src/main/java/com/mensinator/app/database/repositories/PeriodRepository.kt new file mode 100644 index 0000000..85e73fb --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/repositories/PeriodRepository.kt @@ -0,0 +1,57 @@ +package com.mensinator.app.database.repositories + +import com.mensinator.app.database.MensinatorDB +import com.mensinator.app.database.Period +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class PeriodRepository(private val database: MensinatorDB, private val dispatcher: CoroutineDispatcher = Dispatchers.IO) { + + //----- READ ----- + + suspend fun getAllPeriods(): List { + return withContext(dispatcher){ + database.periodQueries.getAllPeriods().executeAsList() + } + } + + suspend fun getPeriodByDate(date: String): Period? { + return withContext(dispatcher){ + database.periodQueries.getPeriodByDate(date).executeAsOneOrNull() + } + } + + suspend fun getAllPeriodsByCycle(cycleId: Long): List { + return withContext(dispatcher){ + database.periodQueries.getAllPeriodsByCycle(cycleId).executeAsList() + } + } + + + //----- CREATE ----- + + suspend fun insertPeriod(date: String, cycleId: Long){ + withContext(dispatcher){ + database.periodQueries.insertPeriod(date, cycleId) + } + } + + + //----- UPDATE ----- + + + //----- DELETE ----- + + suspend fun deletePeriodByDate(date: String){ + withContext(dispatcher){ + database.periodQueries.deletePeriodByDate(date) + } + } + + suspend fun deletePeriodsByCycle(cycleId: Long){ + withContext(dispatcher){ + database.periodQueries.deletePeriodsByCycle(cycleId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/repositories/PredictionRepository.kt b/app/src/main/java/com/mensinator/app/database/repositories/PredictionRepository.kt new file mode 100644 index 0000000..08af5c7 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/repositories/PredictionRepository.kt @@ -0,0 +1,93 @@ +package com.mensinator.app.database.repositories + +import com.mensinator.app.database.MensinatorDB +import com.mensinator.app.database.Prediction +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class PredictionRepository(private val database: MensinatorDB, private val dispatcher: CoroutineDispatcher = Dispatchers.IO) { + + //----- READ ----- + + suspend fun getAllPredictions(): List { + return withContext(dispatcher){ + database.predictionQueries.getAllPredictions().executeAsList() + } + } + + suspend fun getPredictionsByType(type: String): List { + return withContext(dispatcher){ + database.predictionQueries.getPredictionsByType(type).executeAsList() + } + } + + suspend fun getPredictionsByCycle(cycleId: Long): List { + return withContext(dispatcher){ + database.predictionQueries.getPredictionsByCycle(cycleId).executeAsList() + } + } + + suspend fun getPredictionsByMonth(startDate: String, endDate: String): List { + return withContext(dispatcher){ + database.predictionQueries.getPredictionsByMonth(startDate, endDate).executeAsList() + } + } + + suspend fun getPredictionsByTypeCycle(type: String, cycleId: Long): List { + return withContext(dispatcher){ + database.predictionQueries.getPredictionsByTypeCycle(type, cycleId).executeAsList() + } + } + + suspend fun getPredictionsByTypeMonth(type: String, startDate: String, endDate: String): List { + return withContext(dispatcher){ + database.predictionQueries.getPredictionsByTypeMonth(type, startDate, endDate).executeAsList() + } + } + + + //----- CREATE ----- + + suspend fun insertPrediction(date: String, type: String, cycleId: Long){ + withContext(dispatcher){ + database.predictionQueries.insertPrediction(date, type, cycleId) + } + } + + + //----- UPDATE ----- + + + //----- DELETE ----- + + suspend fun deletePredictionsByCycle(cycleId: Long) { + withContext(dispatcher){ + database.predictionQueries.deletePredictionsByCycle(cycleId) + } + } + + suspend fun deletePredictionsByMonth(startDate: String, endDate: String) { + withContext(dispatcher){ + database.predictionQueries.deletePredictionsByMonth(startDate, endDate) + } + } + + suspend fun deletePredictionsByTypeCycle(type: String, cycleId: Long) { + withContext(dispatcher){ + database.predictionQueries.deletePredictionsByTypeCycle(type, cycleId) + } + } + + suspend fun deletePredictionsByTypeMonth(type: String, startDate: String, endDate: String) { + withContext(dispatcher){ + database.predictionQueries.deletePredictionsByTypeMonth(type, startDate, endDate) + } + } + + suspend fun deletePredictionsByDate(date: String) { + withContext(dispatcher){ + database.predictionQueries.deletePredictionsByDate(date) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/viewmodels/AppSettingViewModel.kt b/app/src/main/java/com/mensinator/app/database/viewmodels/AppSettingViewModel.kt new file mode 100644 index 0000000..e0f80a3 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/viewmodels/AppSettingViewModel.kt @@ -0,0 +1,63 @@ +package com.mensinator.app.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mensinator.app.database.App_setting +import com.mensinator.app.database.repositories.AppSettingRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +class AppSettingViewModel(private val appSettingRepository: AppSettingRepository): ViewModel() { + + private val _appSettingsCategory = MutableStateFlow>(emptyList()) + val appSettingsCategory: StateFlow> = _appSettingsCategory + + + //----- READ ----- + + fun loadAllSettings(){ + viewModelScope.launch { + _appSettingsCategory.value = appSettingRepository.getAllSettings() + } + } + + fun loadSettingsCategory(category: String){ + viewModelScope.launch { + _appSettingsCategory.value = appSettingRepository.getAllSettingsByCategory(category) + } + } + + + //----- CREATE ----- + + fun addSetting(label: String, value: String, category: String){ + viewModelScope.launch { + appSettingRepository.insertAppSetting(label, value, category) + } + } + + + //----- UPDATE ----- + + fun changeSettingValue(value: String, label: String){ + viewModelScope.launch { + appSettingRepository.setAppSettingValue(value, label) + } + } + + + //----- DELETE ----- + + fun deleteSettingByLabel(label: String){ + viewModelScope.launch { + appSettingRepository.deleteAppSettingByLabel(label) + } + } + + fun deleteSettingByCategory(category: String){ + viewModelScope.launch { + appSettingRepository.deleteAppSettingsByCategory(category) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/viewmodels/CycleViewModel.kt b/app/src/main/java/com/mensinator/app/database/viewmodels/CycleViewModel.kt new file mode 100644 index 0000000..9e52ec0 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/viewmodels/CycleViewModel.kt @@ -0,0 +1,89 @@ +package com.mensinator.app.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mensinator.app.database.Cycle +import com.mensinator.app.database.repositories.CycleRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +class CycleViewModel(private val cycleRepository: CycleRepository): ViewModel() { + + private val _cycles = MutableStateFlow>(emptyList()) + val cycles: StateFlow> = _cycles + + private val _dateCycles = MutableStateFlow>(emptyList()) + val dateCycles: StateFlow> = _dateCycles + + + //----- READ ----- + + fun loadCycles(){ + viewModelScope.launch { + _cycles.value = cycleRepository.getAllCycles() + } + } + + fun loadCyclesByDate(startDate: String, endDate: String){ + viewModelScope.launch { + _dateCycles.value = cycleRepository.getAllCyclesByInterval(startDate, endDate) + } + } + + + //----- CREATE ----- + + fun addCycle(startDate: String, endDate: String, length: Long, lutealPhaseLength: Long){ + viewModelScope.launch { + cycleRepository.insertCycle(startDate, endDate, length, lutealPhaseLength) + } + } + + fun addCycleByStartDate(startDate: String){ + viewModelScope.launch { + cycleRepository.insertCycleByStartDate(startDate) + } + } + + + //----- UPDATE ----- + + fun changeCycleEndDate(endDate: String, id: Long){ + viewModelScope.launch { + cycleRepository.setCycleEndDate(endDate, id) + loadCycles() + } + } + + fun changeCycleLength(length: Long, id: Long){ + viewModelScope.launch { + cycleRepository.setCycleLength(length, id) + loadCycles() + } + } + + fun changeCycleLutealLength(lutealPhaseLength: Long, id: Long){ + viewModelScope.launch{ + cycleRepository.setCycleLutealLength(lutealPhaseLength, id) + loadCycles() + } + } + + + //----- DELETE ----- + + fun deleteCycleById(id: Long){ + viewModelScope.launch { + cycleRepository.deleteCycleById(id) + loadCycles() + } + } + + fun deleteCycleByStartDate(startDate: String){ + viewModelScope.launch { + cycleRepository.deleteCycleByStartDate(startDate) + loadCycles() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/viewmodels/NoteViewModel.kt b/app/src/main/java/com/mensinator/app/database/viewmodels/NoteViewModel.kt new file mode 100644 index 0000000..4a37c24 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/viewmodels/NoteViewModel.kt @@ -0,0 +1,103 @@ +package com.mensinator.app.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mensinator.app.database.Note +import com.mensinator.app.database.Note_date +import com.mensinator.app.database.repositories.NoteRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +class NoteViewModel(private val noteRepository: NoteRepository): ViewModel() { + + private val _notes = MutableStateFlow>(emptyList()) + val notes: StateFlow> = _notes + + private val _noteDates = MutableStateFlow>(emptyList()) + val noteDates: StateFlow> = _noteDates + + + //----- READ ----- + + fun loadAllNotes(){ + viewModelScope.launch { + _notes.value = noteRepository.getAllNotes() + } + } + + fun loadNotesByCategory(category: String){ + viewModelScope.launch { + _notes.value = noteRepository.getAllNotesByCategory(category) + } + } + + fun loadNotesByDate(date: String){ + viewModelScope.launch { + _notes.value = noteRepository.getAllNotesByDate(date) + } + } + + fun loadDatesByNote(name: String){ + viewModelScope.launch { + _noteDates.value = noteRepository.getAllDatesByNote(name) + } + } + + + //----- CREATE ----- + + fun addNote(name: String, category: String, isActive: Boolean){ + viewModelScope.launch { + noteRepository.insertNote(name, category, isActive) + } + } + + fun addNoteDate(date: String){ + viewModelScope.launch { + noteRepository.insertNoteDate(date) + } + } + + fun addNoteDateCrossRef(noteId: Long, noteDateId: Long){ + viewModelScope.launch { + noteRepository.insertNoteDateCrossRef(noteId, noteDateId) + } + } + + + //----- UPDATE ----- + + fun toggleActiveStatus(name: String){ + viewModelScope.launch { + noteRepository.toggleNoteActiveStatus(name) + } + } + + + //----- DELETE ----- + + fun deleteNoteByName(name: String){ + viewModelScope.launch { + noteRepository.deleteNoteByName(name) + } + } + + fun deleteNotesByCategory(category: String){ + viewModelScope.launch { + noteRepository.deleteNotesByCategory(category) + } + } + + fun deleteNoteDate(date: String){ + viewModelScope.launch { + noteRepository.deleteNoteDate(date) + } + } + + fun deleteNoteDateCrossRef(noteId: Long, noteDateId: Long){ + viewModelScope.launch { + noteRepository.deleteNoteDateCrossRef(noteId, noteDateId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/viewmodels/OvulationViewModel.kt b/app/src/main/java/com/mensinator/app/database/viewmodels/OvulationViewModel.kt new file mode 100644 index 0000000..d00c023 --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/viewmodels/OvulationViewModel.kt @@ -0,0 +1,57 @@ +package com.mensinator.app.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mensinator.app.database.Ovulation +import com.mensinator.app.database.repositories.OvulationRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +class OvulationViewModel(private val ovulationRepository: OvulationRepository): ViewModel() { + + private val _ovulation = MutableStateFlow(null) + val ovulation: StateFlow = _ovulation + + + //----- READ ----- + + fun loadByDate(date: String){ + viewModelScope.launch { + _ovulation.value = ovulationRepository.getOvulationByDate(date) + } + } + + fun loadByCycle(cycleId: Long){ + viewModelScope.launch { + _ovulation.value = ovulationRepository.getOvulationByCycle(cycleId) + } + } + + + //----- CREATE ----- + + fun addOvulation(date: String, cycleId: Long){ + viewModelScope.launch { + ovulationRepository.insertOvulation(date, cycleId) + } + } + + + //----- UPDATE ----- + + + //----- DELETE ----- + + fun deleteByDate(date: String){ + viewModelScope.launch { + ovulationRepository.deleteOvulationByDate(date) + } + } + + fun deleteByCycle(cycleId: Long){ + viewModelScope.launch { + ovulationRepository.deleteOvulationByCycle(cycleId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/viewmodels/PeriodViewModel.kt b/app/src/main/java/com/mensinator/app/database/viewmodels/PeriodViewModel.kt new file mode 100644 index 0000000..72d5f1f --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/viewmodels/PeriodViewModel.kt @@ -0,0 +1,60 @@ +package com.mensinator.app.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mensinator.app.database.Period +import com.mensinator.app.database.repositories.PeriodRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +class PeriodViewModel(private val periodRepository: PeriodRepository): ViewModel() { + + private val _periods = MutableStateFlow>(emptyList()) + val periods: StateFlow> = _periods + + private val _period = MutableStateFlow(null) + val period: StateFlow = _period + + + //----- READ ----- + + fun loadByDate(date: String){ + viewModelScope.launch { + _period.value = periodRepository.getPeriodByDate(date) + } + } + + fun loadByCycle(cycleId: Long){ + viewModelScope.launch { + _periods.value = periodRepository.getAllPeriodsByCycle(cycleId) + } + } + + + //----- CREATE ----- + + fun addPeriod(date: String, cycleId: Long){ + viewModelScope.launch { + periodRepository.insertPeriod(date, cycleId) + } + } + + + //----- UPDATE ----- + + + //----- DELETE ----- + + fun deleteByDate(date: String){ + viewModelScope.launch { + periodRepository.deletePeriodByDate(date) + } + } + + fun deleteByCycle(cycleId: Long){ + viewModelScope.launch { + periodRepository.deletePeriodsByCycle(cycleId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mensinator/app/database/viewmodels/PredictionViewModel.kt b/app/src/main/java/com/mensinator/app/database/viewmodels/PredictionViewModel.kt new file mode 100644 index 0000000..f0957ab --- /dev/null +++ b/app/src/main/java/com/mensinator/app/database/viewmodels/PredictionViewModel.kt @@ -0,0 +1,92 @@ +package com.mensinator.app.database.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mensinator.app.database.Prediction +import com.mensinator.app.database.repositories.PredictionRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch + +class PredictionViewModel(private val predictionRepository: PredictionRepository): ViewModel() { + + private val _predictions = MutableStateFlow>(emptyList()) + val prediction: StateFlow> = _predictions + + //----- READ ----- + + fun loadByType(type: String){ + viewModelScope.launch { + _predictions.value = predictionRepository.getPredictionsByType(type) + } + } + + fun loadByCycle(cycleId: Long){ + viewModelScope.launch { + _predictions.value = predictionRepository.getPredictionsByCycle(cycleId) + } + } + + fun loadByMonth(startDate: String, endDate: String){ + viewModelScope.launch { + _predictions.value = predictionRepository.getPredictionsByMonth(startDate, endDate) + } + } + + fun loadByTypeCycle(type: String, cycleId: Long){ + viewModelScope.launch { + _predictions.value = predictionRepository.getPredictionsByTypeCycle(type, cycleId) + } + } + + fun loadByTypeMonth(type: String, startDate: String, endDate: String){ + viewModelScope.launch { + _predictions.value = predictionRepository.getPredictionsByTypeMonth(type, startDate, endDate) + } + } + + + //----- CREATE ----- + + fun addPrediction(date: String, type: String, cycleId: Long){ + viewModelScope.launch { + predictionRepository.insertPrediction(date, type, cycleId) + } + } + + + //----- UPDATE ----- + + + //----- DELETE ----- + + fun deleteByCycle(cycleId: Long){ + viewModelScope.launch { + predictionRepository.deletePredictionsByCycle(cycleId) + } + } + + fun deleteByMonth(startDate: String, endDate: String){ + viewModelScope.launch { + predictionRepository.deletePredictionsByMonth(startDate, endDate) + } + } + + fun deleteByTypeCycle(type: String, cycleId: Long){ + viewModelScope.launch { + predictionRepository.deletePredictionsByTypeCycle(type, cycleId) + } + } + + fun deleteByTypeMonth(type: String, startDate: String, endDate: String){ + viewModelScope.launch { + predictionRepository.deletePredictionsByTypeMonth(type, startDate, endDate) + } + } + + fun deleteByDate(date: String){ + viewModelScope.launch { + predictionRepository.deletePredictionsByDate(date) + } + } +} \ No newline at end of file diff --git a/app/src/main/sqldelight/com/mensinator/app/database/AppSetting.sq b/app/src/main/sqldelight/com/mensinator/app/database/AppSetting.sq new file mode 100644 index 0000000..f0487c5 --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/AppSetting.sq @@ -0,0 +1,41 @@ +CREATE TABLE app_setting ( +id INTEGER PRIMARY KEY AUTOINCREMENT, +label TEXT NOT NULL UNIQUE, +value TEXT NOT NULL, +category TEXT NOT NULL +); + + +-- SELECT QUERIES -- +-------------------- + +getAllSettings: +SELECT * FROM app_setting; + +getAllSettingsByCategory: +SELECT * FROM app_setting WHERE category = ?; + + +-- INSERT QUERIES -- +-------------------- + +insertAppSetting: +INSERT OR REPLACE INTO app_setting(label, value, category) VALUES (?,?,?); + + +-- UPDATE QUERIES -- +-------------------- + +setAppSettingValue: +UPDATE app_setting SET value = ? WHERE label = ?; + + +-- DELETE QUERIES -- +-------------------- + +deleteAppSettingByLabel: +DELETE FROM app_setting WHERE label = ?; + +deleteAppSettingsByCategory: +DELETE FROM app_setting WHERE category = ?; + diff --git a/app/src/main/sqldelight/com/mensinator/app/database/Cycle.sq b/app/src/main/sqldelight/com/mensinator/app/database/Cycle.sq new file mode 100644 index 0000000..a9c7018 --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/Cycle.sq @@ -0,0 +1,50 @@ +CREATE TABLE cycle( +id INTEGER PRIMARY KEY AUTOINCREMENT, +start_date TEXT NOT NULL UNIQUE, +end_date TEXT, +length INTEGER, +luteal_phase_length INTEGER +); + + +-- SELECT QUERIES -- +-------------------- + +getAllCycles: +SELECT * FROM cycle; + +getAllCyclesByInterval: +SELECT * FROM cycle WHERE start_date BETWEEN ? AND ?; + + +-- INSERT QUERIES -- +-------------------- + +insertCycle: +INSERT OR REPLACE INTO cycle(start_date, end_date, length, luteal_phase_length) VALUES (?,?,?,?); + +insertCycleByStartDate: +INSERT OR REPLACE INTO cycle(start_date) VALUES (?); + + +-- UPDATE QUERIES -- +-------------------- + +setCycleEndDate: +UPDATE cycle SET end_date = ? WHERE id = ?; + +setCycleLength: +UPDATE cycle SET length = ? WHERE id = ?; + +setCycleLutealLength: +UPDATE cycle SET luteal_phase_length = ? WHERE id = ?; + + +-- DELETE QUERIES -- +-------------------- + +deleteCycleById: +DELETE FROM cycle WHERE id = ?; + +deleteCycleByStartDate: +DELETE FROM cycle WHERE start_date = ?; diff --git a/app/src/main/sqldelight/com/mensinator/app/database/Note.sq b/app/src/main/sqldelight/com/mensinator/app/database/Note.sq new file mode 100644 index 0000000..7f7ed4e --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/Note.sq @@ -0,0 +1,56 @@ +import kotlin.Boolean; + +CREATE TABLE note( +id INTEGER PRIMARY KEY AUTOINCREMENT, +name TEXT NOT NULL UNIQUE, +category TEXT NOT NULL, +is_active INTEGER AS Boolean NOT NULL +); + + +-- SELECT QUERIES -- +-------------------- + +getAllNotes: +SELECT * FROM note; + +getAllNotesByCategory: +SELECT * FROM note WHERE category = ?; + +getAllNotesByDate: +SELECT note.* +FROM note +INNER JOIN note_date_cross_ref nd_cr ON note.id = nd_cr.note_id +INNER JOIN note_date ON nd_cr.note_date_id = note_date.id +WHERE note_date.date = ?; + + +-- INSERT QUERIES -- +-------------------- + +insertNote: +INSERT OR REPLACE INTO note (name, category, is_active) +VALUES (?, ?, ?); + + +-- UPDATE QUERIES -- +-------------------- + +toggleNoteActiveStatus: +UPDATE note +SET is_active = CASE + WHEN is_active = 1 THEN 0 + WHEN is_active = 0 THEN 1 + ELSE is_active +END +WHERE name = ?; + + +-- DELETE QUERIES -- +-------------------- + +deleteNoteByName: +DELETE FROM note WHERE name = ?; + +deleteNotesByCategory: +DELETE FROM note WHERE category = ?; \ No newline at end of file diff --git a/app/src/main/sqldelight/com/mensinator/app/database/NoteDate.sq b/app/src/main/sqldelight/com/mensinator/app/database/NoteDate.sq new file mode 100644 index 0000000..f5f50e3 --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/NoteDate.sq @@ -0,0 +1,36 @@ +CREATE TABLE note_date( +id INTEGER PRIMARY KEY AUTOINCREMENT, +date TEXT NOT NULL UNIQUE +); + + +-- SELECT QUERIES -- +-------------------- + +getAllNoteDates: +SELECT * FROM note_date; + +getAllDatesByNote: +SELECT note_date.* +FROM note_date +INNER JOIN note_date_cross_ref nd_cr ON note_date.id = nd_cr.note_date_id +INNER JOIN note ON nd_cr.note_id = note.id +WHERE note.name = ?; + + +-- INSERT QUERIES -- +-------------------- + +insertNoteDate: +INSERT OR REPLACE INTO note_date(date) VALUES (?); + + +-- UPDATE QUERIES -- +-------------------- + + +-- DELETE QUERIES -- +-------------------- + +deleteNoteDate: +DELETE FROM note_date WHERE date = ?; \ No newline at end of file diff --git a/app/src/main/sqldelight/com/mensinator/app/database/NoteDateCrossRef.sq b/app/src/main/sqldelight/com/mensinator/app/database/NoteDateCrossRef.sq new file mode 100644 index 0000000..5bcd3b7 --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/NoteDateCrossRef.sq @@ -0,0 +1,31 @@ +CREATE TABLE note_date_cross_ref( +note_id INTEGER, +note_date_id INTEGER, +PRIMARY KEY (note_id, note_date_id), +FOREIGN KEY (note_id) REFERENCES note(id), +FOREIGN KEY (note_date_id) REFERENCES note_date(id) +); + + +-- SELECT QUERIES -- +-------------------- + +getAllNoteDateCrossRefs: +SELECT * FROM note_date_cross_ref; + +-- INSERT QUERIES -- +-------------------- + +insertNoteDateCrossRef: +INSERT OR REPLACE INTO note_date_cross_ref(note_id, note_date_id) VALUES (?,?); + + +-- UPDATE QUERIES -- +-------------------- + + +-- DELETE QUERIES -- +-------------------- + +deleteNoteDateCrossRef: +DELETE FROM note_date_cross_ref WHERE note_id = ? AND note_date_id = ?; diff --git a/app/src/main/sqldelight/com/mensinator/app/database/Ovulation.sq b/app/src/main/sqldelight/com/mensinator/app/database/Ovulation.sq new file mode 100644 index 0000000..e367c69 --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/Ovulation.sq @@ -0,0 +1,40 @@ +CREATE TABLE ovulation( +id INTEGER PRIMARY KEY AUTOINCREMENT, +date TEXT NOT NULL, +cycle_id INTEGER, +FOREIGN KEY (cycle_id) REFERENCES cycle(id) +); + + +-- SELECT QUERIES -- +-------------------- + +getAllOvulations: +SELECT * FROM ovulation; + +getOvulationByDate: +SELECT * FROM ovulation WHERE date = ?; + +getOvulationByCycle: +SELECT * FROM ovulation WHERE cycle_id = ?; + + +-- INSERT QUERIES -- +-------------------- + +insertOvulation: +INSERT OR REPLACE INTO ovulation(date, cycle_id) VALUES (?,?); + + +-- UPDATE QUERIES -- +-------------------- + + +-- DELETE QUERIES -- +-------------------- + +deleteOvulationByDate: +DELETE FROM ovulation WHERE date = ?; + +deleteOvulationByCycle: +DELETE FROM ovulation WHERE cycle_id = ?; \ No newline at end of file diff --git a/app/src/main/sqldelight/com/mensinator/app/database/Period.sq b/app/src/main/sqldelight/com/mensinator/app/database/Period.sq new file mode 100644 index 0000000..23d1282 --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/Period.sq @@ -0,0 +1,40 @@ +CREATE TABLE period( +id INTEGER PRIMARY KEY AUTOINCREMENT, +date TEXT NOT NULL, +cycle_id INTEGER, +FOREIGN KEY (cycle_id) REFERENCES cycle(id) +); + + +-- SELECT QUERIES -- +-------------------- + +getAllPeriods: +SELECT * FROM period; + +getPeriodByDate: +SELECT * FROM period WHERE date = ?; + +getAllPeriodsByCycle: +SELECT * FROM period WHERE cycle_id = ?; + + +-- INSERT QUERIES -- +-------------------- + +insertPeriod: +INSERT OR REPLACE INTO period(date, cycle_id) VALUES (?,?); + + +-- UPDATE QUERIES -- +-------------------- + + +-- DELETE QUERIES -- +-------------------- + +deletePeriodByDate: +DELETE FROM period WHERE date = ?; + +deletePeriodsByCycle: +DELETE FROM period WHERE cycle_id = ?; diff --git a/app/src/main/sqldelight/com/mensinator/app/database/Prediction.sq b/app/src/main/sqldelight/com/mensinator/app/database/Prediction.sq new file mode 100644 index 0000000..bfcc85d --- /dev/null +++ b/app/src/main/sqldelight/com/mensinator/app/database/Prediction.sq @@ -0,0 +1,60 @@ +CREATE TABLE prediction( +id INTEGER PRIMARY KEY AUTOINCREMENT, +date TEXT NOT NULL, +type TEXT NOT NULL, +cycle_id INTEGER, +FOREIGN KEY (cycle_id) REFERENCES cycle(id) +); + + +-- SELECT QUERIES -- +-------------------- + +getAllPredictions: +SELECT * FROM prediction; + +getPredictionsByType: +SELECT * FROM prediction WHERE type = ?; + +getPredictionsByCycle: +SELECT * FROM prediction WHERE cycle_id = ?; + +getPredictionsByMonth: +SELECT * FROM prediction WHERE date BETWEEN ? AND ?; + +getPredictionsByTypeCycle: +SELECT * FROM prediction WHERE type = ? AND cycle_id = ?; + +getPredictionsByTypeMonth: +SELECT * FROM prediction WHERE type = ? AND date BETWEEN ? AND ?; + + +-- INSERT QUERIES -- +-------------------- + +insertPrediction: +INSERT OR REPLACE INTO prediction(date, type, cycle_id) VALUES (?,?,?); + + +-- UPDATE QUERIES -- +-------------------- + + +-- DELETE QUERIES -- +-------------------- + +deletePredictionsByCycle: +DELETE FROM prediction WHERE cycle_id = ?; + +deletePredictionsByMonth: +DELETE FROM prediction WHERE date BETWEEN ? AND ?; + +deletePredictionsByDate: +DELETE FROM prediction WHERE date = ?; + +deletePredictionsByTypeCycle: +DELETE FROM prediction WHERE type = ? AND cycle_id = ?; + +deletePredictionsByTypeMonth: +DELETE FROM prediction WHERE type = ? AND date BETWEEN ? AND ?; + diff --git a/build.gradle.kts b/build.gradle.kts index f74b04b..7a9f004 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.jetbrains.kotlin.android) apply false + id("app.cash.sqldelight") version "2.0.2" apply false } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fdcb303..c605bc6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,12 +5,11 @@ coreKtx = "1.13.1" junit = "4.13.2" junitVersion = "1.2.1" espressoCore = "3.6.1" -lifecycleRuntimeKtx = "2.8.3" -activityCompose = "1.9.0" -composeBom = "2024.04.01" +lifecycleRuntimeKtx = "2.8.4" +activityCompose = "1.9.1" +composeBom = "2024.06.00" window = "1.3.0" -workRuntimeKtx = "2.9.0" -places = "3.5.0" +workRuntimeKtx = "2.9.1" appcompat = "1.7.0" navigationRuntimeKtx = "2.7.7" navigationCompose = "2.7.7" @@ -33,7 +32,7 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit androidx-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-window = { group = "androidx.window", name = "window", version.ref = "window" } androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workRuntimeKtx" } -places = { group = "com.google.android.libraries.places", name = "places", version.ref = "places" } +koin-android = { module = "io.insert-koin:koin-android", version = "4.0.0-RC1" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } androidx-navigation-runtime-ktx = { group = "androidx.navigation", name = "navigation-runtime-ktx", version.ref = "navigationRuntimeKtx" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }