Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
/app/build
98 changes: 98 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("kotlin-kapt")
id("com.google.dagger.hilt.android")
}

android {
namespace = "com.apartment.planner"
compileSdk = 34

defaultConfig {
applicationId = "com.apartment.planner"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
kotlinOptions {
jvmTarget = "21"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.10"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}

dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.activity:activity-compose:1.8.2")
implementation(platform("androidx.compose:compose-bom:2024.02.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3:1.2.0")
implementation("androidx.compose.ui:ui-text-google-fonts:1.6.1")

// Coil
implementation("io.coil-kt:coil-compose:2.5.0")

// Architecture
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")

// Database
implementation("androidx.room:room-runtime:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")

// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")

// Navigation
implementation("androidx.navigation:navigation-compose:2.7.6")

// DI
implementation("com.google.dagger:hilt-android:2.50")
kapt("com.google.dagger:hilt-compiler:2.50")
implementation("androidx.hilt:hilt-navigation-compose:1.1.0")

// Lottie
implementation("com.airbnb.android:lottie-compose:6.3.0")

testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2024.02.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}
40 changes: 40 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application
android:name=".PlannerApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher_foreground"
android:label="@string/app_name"
android:roundIcon="@drawable/ic_launcher_foreground"
android:supportsRtl="true"
android:theme="@style/Theme.SmallApartmentDecorPlanner">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.SmallApartmentDecorPlanner">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- Share intent integration -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>

</manifest>
31 changes: 31 additions & 0 deletions app/src/main/kotlin/com/apartment/planner/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.apartment.planner

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.navigation.compose.rememberNavController
import com.apartment.planner.ui.navigation.NavGraph
import com.apartment.planner.ui.theme.DecorPlannerTheme
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DecorPlannerTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val navController = rememberNavController()
NavGraph(navController = navController)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.apartment.planner

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class PlannerApplication : Application()
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.apartment.planner.data.local

import androidx.room.Database
import androidx.room.RoomDatabase
import com.apartment.planner.data.local.dao.*
import com.apartment.planner.data.local.entity.*

@Database(
entities = [
ApartmentEntity::class,
RoomEntity::class,
PinEntity::class,
ChecklistItemEntity::class,
BudgetItemEntity::class
],
version = 1,
exportSchema = false
)
abstract class PlannerDatabase : RoomDatabase() {
abstract fun apartmentDao(): ApartmentDao
abstract fun roomDao(): RoomDao
abstract fun pinDao(): PinDao
abstract fun checklistDao(): ChecklistDao
abstract fun budgetDao(): BudgetDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.apartment.planner.data.local.dao

import androidx.room.*
import com.apartment.planner.data.local.entity.ApartmentEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface ApartmentDao {
@Query("SELECT * FROM apartments LIMIT 1")
fun getApartment(): Flow<ApartmentEntity?>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertApartment(apartment: ApartmentEntity)

@Update
suspend fun updateApartment(apartment: ApartmentEntity)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.apartment.planner.data.local.dao

import androidx.room.*
import com.apartment.planner.data.local.entity.BudgetItemEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface BudgetDao {
@Query("SELECT * FROM budget_items WHERE roomId = :roomId ORDER BY createdAt ASC")
fun getItemsByRoom(roomId: String): Flow<List<BudgetItemEntity>>

@Query("SELECT * FROM budget_items ORDER BY createdAt ASC")
fun getAllBudgetItems(): Flow<List<BudgetItemEntity>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertItem(item: BudgetItemEntity)

@Update
suspend fun updateItem(item: BudgetItemEntity)

@Delete
suspend fun deleteItem(item: BudgetItemEntity)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.apartment.planner.data.local.dao

import androidx.room.*
import com.apartment.planner.data.local.entity.ChecklistItemEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface ChecklistDao {
@Query("SELECT * FROM checklist_items WHERE roomId = :roomId ORDER BY displayOrder ASC")
fun getItemsByRoom(roomId: String): Flow<List<ChecklistItemEntity>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertItem(item: ChecklistItemEntity)

@Update
suspend fun updateItem(item: ChecklistItemEntity)

@Delete
suspend fun deleteItem(item: ChecklistItemEntity)
}
23 changes: 23 additions & 0 deletions app/src/main/kotlin/com/apartment/planner/data/local/dao/PinDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.apartment.planner.data.local.dao

import androidx.room.*
import com.apartment.planner.data.local.entity.PinEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface PinDao {
@Query("SELECT * FROM pins WHERE roomId = :roomId ORDER BY displayOrder ASC")
fun getPinsByRoom(roomId: String): Flow<List<PinEntity>>

@Query("SELECT * FROM pins WHERE id = :pinId")
suspend fun getPinById(pinId: String): PinEntity?

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertPin(pin: PinEntity)

@Update
suspend fun updatePin(pin: PinEntity)

@Delete
suspend fun deletePin(pin: PinEntity)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.apartment.planner.data.local.dao

import androidx.room.*
import com.apartment.planner.data.local.entity.RoomEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface RoomDao {
@Query("SELECT * FROM rooms ORDER BY displayOrder ASC")
fun getAllRooms(): Flow<List<RoomEntity>>

@Query("SELECT * FROM rooms WHERE id = :roomId")
suspend fun getRoomById(roomId: String): RoomEntity?

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertRoom(room: RoomEntity)

@Update
suspend fun updateRoom(room: RoomEntity)

@Delete
suspend fun deleteRoom(room: RoomEntity)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.apartment.planner.data.local.entity

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "apartments")
data class ApartmentEntity(
@PrimaryKey val id: String,
val name: String,
val type: String, // STUDIO, ONE_BR, TWO_BR
val sizeRange: String?, // UNDER_30, 30_TO_50, OVER_50
val notes: String,
val createdAt: Long,
val updatedAt: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.apartment.planner.data.local.entity

import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey

@Entity(
tableName = "budget_items",
foreignKeys = [
ForeignKey(
entity = RoomEntity::class,
parentColumns = ["id"],
childColumns = ["roomId"],
onDelete = ForeignKey.CASCADE
)
],
indices = [Index(value = ["roomId"])]
)
data class BudgetItemEntity(
@PrimaryKey val id: String,
val roomId: String,
val name: String,
val category: String,
val estimatedCost: Double,
val actualCost: Double?,
val linkedPinId: String?,
val status: String, // PLANNED, BOUGHT
val createdAt: Long
)
Loading