Skip to content
This repository was archived by the owner on Jul 20, 2026. It is now read-only.

Commit 06c7525

Browse files
committed
supervisor and account info pages
1 parent 00f737c commit 06c7525

14 files changed

Lines changed: 684 additions & 173 deletions

File tree

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package com.example.senpos.data.models
22

3+
enum class AccountType {
4+
SENIOR,
5+
SUPERVISOR
6+
}
7+
38
data class User(
49
val id: String,
510
val firstName: String,
611
val lastName: String,
712
val email: String,
8-
val password: String
13+
val password: String,
14+
val accountType: AccountType,
15+
val linkCode: String,
16+
val linkedSeniorId: String? = null
917
)
Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,53 @@
11
package com.example.senpos.data.repositories
22

3+
import com.example.senpos.data.models.AccountType
34
import com.example.senpos.data.models.User
45
import kotlinx.coroutines.flow.MutableStateFlow
56
import kotlinx.coroutines.flow.StateFlow
67
import kotlinx.coroutines.flow.asStateFlow
8+
import java.util.UUID
79

810
interface AuthRepository {
911
val currentUser: StateFlow<User?>
1012
suspend fun login(email: String, password: String): User?
11-
suspend fun signup(name: String, surname: String, email: String, password: String): User?
13+
suspend fun signup(
14+
name: String,
15+
surname: String,
16+
email: String,
17+
password: String,
18+
accountType: AccountType,
19+
supervisorLinkCode: String? = null // requis si accountType == SUPERVISOR
20+
): User?
1221
suspend fun logout()
22+
23+
suspend fun findSeniorByLinkCode(linkCode: String): User?
1324
}
1425

1526
class OfflineAuthRepository : AuthRepository {
1627
private val _currentUser = MutableStateFlow<User?>(null)
1728
override val currentUser: StateFlow<User?> = _currentUser.asStateFlow()
1829

1930
private val users = mutableListOf(
31+
// senior
32+
User(
33+
id = "user_1",
34+
firstName = "Waltuh",
35+
lastName = "HelpMe",
36+
email = "im.a@labubu.waltuh",
37+
password = "feet",
38+
accountType = AccountType.SENIOR,
39+
linkCode = "WALT-1234"
40+
),
41+
// superviseur
2042
User(
21-
id = "user_1",
22-
firstName = "Waltuh",
23-
lastName = "HelpMe",
24-
email = "im.a@labubu.waltuh",
25-
password = "feet"
43+
id = "user_2",
44+
firstName = "Jesse",
45+
lastName = "Pinkman",
46+
email = "jesse@supervisor.com",
47+
password = "yo",
48+
accountType = AccountType.SUPERVISOR,
49+
linkCode = "JESSE-5678",
50+
linkedSeniorId = "user_1"
2651
)
2752
)
2853

@@ -32,21 +57,53 @@ class OfflineAuthRepository : AuthRepository {
3257
return user
3358
}
3459

35-
override suspend fun signup(name: String, surname: String, email: String, password: String): User? {
60+
override suspend fun signup(
61+
name: String,
62+
surname: String,
63+
email: String,
64+
password: String,
65+
accountType: AccountType,
66+
supervisorLinkCode: String?
67+
): User? {
3668
if (users.any { it.email == email }) return null
37-
69+
70+
var linkedSeniorId: String? = null
71+
72+
if (accountType == AccountType.SUPERVISOR) {
73+
if (supervisorLinkCode.isNullOrBlank()) return null
74+
val senior = users.find {
75+
it.accountType == AccountType.SENIOR && it.linkCode == supervisorLinkCode
76+
} ?: return null
77+
linkedSeniorId = senior.id
78+
}
79+
3880
val newUser = User(
39-
id = java.util.UUID.randomUUID().toString(),
40-
firstName = name,
41-
lastName = surname,
42-
email = email,
43-
password = password
81+
id = UUID.randomUUID().toString(),
82+
firstName = name,
83+
lastName = surname,
84+
email = email,
85+
password = password,
86+
accountType = accountType,
87+
linkCode = generateLinkCode(name),
88+
linkedSeniorId = linkedSeniorId
4489
)
4590
users.add(newUser)
4691
return newUser
4792
}
4893

94+
override suspend fun findSeniorByLinkCode(linkCode: String): User? {
95+
return users.find {
96+
it.accountType == AccountType.SENIOR && it.linkCode == linkCode
97+
}
98+
}
99+
49100
override suspend fun logout() {
50101
_currentUser.value = null
51102
}
52-
}
103+
104+
private fun generateLinkCode(name: String): String {
105+
val prefix = name.take(4).uppercase().ifBlank { "USER" }
106+
val suffix = (1000..9999).random()
107+
return "$prefix-$suffix"
108+
}
109+
}

app/src/main/java/com/example/senpos/data/repositories/MedicationRepository.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@ class OfflineMedicationRepository : MedicationRepository {
3838
override val plans: StateFlow<List<MedicationPlan>> = _plans.asStateFlow()
3939

4040
private val _intakes = MutableStateFlow(listOf(
41-
MedicationIntake(id = "t1", realIntakeTime = todayAt(7), status = IntakeStatus.PENDING, drugId = "drug_1", planId = "plan_1"),
41+
MedicationIntake(id = "t1", realIntakeTime = todayAt(7), status = IntakeStatus.TAKEN, drugId = "drug_1", planId = "plan_1"),
4242
MedicationIntake(id = "t2", realIntakeTime = todayAt(15), status = IntakeStatus.PENDING, drugId = "drug_1", planId = "plan_1"),
4343
MedicationIntake(id = "t3", realIntakeTime = todayAt(23), status = IntakeStatus.PENDING, drugId = "drug_1", planId = "plan_1"),
44-
MedicationIntake(id = "t4", realIntakeTime = todayAt(8), status = IntakeStatus.PENDING, drugId = "drug_2", planId = "plan_2"),
44+
MedicationIntake(id = "t4", realIntakeTime = todayAt(8), status = IntakeStatus.TAKEN, drugId = "drug_2", planId = "plan_2"),
4545
MedicationIntake(id = "t5", realIntakeTime = todayAt(20), status = IntakeStatus.PENDING, drugId = "drug_2", planId = "plan_2"),
46-
MedicationIntake(id = "t6", realIntakeTime = todayAt(9), status = IntakeStatus.PENDING, drugId = "drug_3", planId = "plan_3"),
47-
MedicationIntake(id = "t7", realIntakeTime = todayAt(7, 30), status = IntakeStatus.PENDING, drugId = "drug_4", planId = "plan_4"),
48-
MedicationIntake(id = "o1", realIntakeTime = daysAgoAt(1, 7), status = IntakeStatus.PENDING, drugId = "drug_1", planId = "plan_1"),
49-
MedicationIntake(id = "o2", realIntakeTime = daysAgoAt(1, 15), status = IntakeStatus.PENDING, drugId = "drug_1", planId = "plan_1"),
50-
MedicationIntake(id = "o3", realIntakeTime = daysAgoAt(1, 8), status = IntakeStatus.PENDING, drugId = "drug_2", planId = "plan_2"),
51-
MedicationIntake(id = "o4", realIntakeTime = daysAgoAt(2, 9), status = IntakeStatus.PENDING, drugId = "drug_3", planId = "plan_3")
46+
MedicationIntake(id = "t6", realIntakeTime = todayAt(9), status = IntakeStatus.MISSED, drugId = "drug_3", planId = "plan_3"),
47+
MedicationIntake(id = "t7", realIntakeTime = todayAt(7, 30), status = IntakeStatus.TAKEN, drugId = "drug_4", planId = "plan_4"),
48+
MedicationIntake(id = "o1", realIntakeTime = daysAgoAt(1, 7), status = IntakeStatus.TAKEN, drugId = "drug_1", planId = "plan_1"),
49+
MedicationIntake(id = "o2", realIntakeTime = daysAgoAt(1, 15), status = IntakeStatus.MISSED, drugId = "drug_1", planId = "plan_1"),
50+
MedicationIntake(id = "o3", realIntakeTime = daysAgoAt(1, 8), status = IntakeStatus.TAKEN, drugId = "drug_2", planId = "plan_2"),
51+
MedicationIntake(id = "o4", realIntakeTime = daysAgoAt(2, 9), status = IntakeStatus.MISSED, drugId = "drug_3", planId = "plan_3")
5252
))
5353
override val intakes: StateFlow<List<MedicationIntake>> = _intakes.asStateFlow()
5454

app/src/main/java/com/example/senpos/ui/AppViewModelProvider.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,21 @@ import androidx.lifecycle.viewmodel.CreationExtras
88
import androidx.lifecycle.viewmodel.initializer
99
import androidx.lifecycle.viewmodel.viewModelFactory
1010
import com.example.senpos.PillulitoApplication
11+
import com.example.senpos.viewmodels.AccountInfoViewModel
1112
import com.example.senpos.viewmodels.AddPosologyViewModel
1213
import com.example.senpos.viewmodels.AuthViewModel
1314
import com.example.senpos.viewmodels.HistoryViewModel
1415
import com.example.senpos.viewmodels.HomeViewModel
1516
import com.example.senpos.viewmodels.PharmacyViewModel
17+
import com.example.senpos.viewmodels.SupervisorViewModel
1618

1719
object AppViewModelProvider {
1820
val Factory = viewModelFactory {
21+
22+
initializer {
23+
AccountInfoViewModel(pillulitoApplication().container.authRepository)
24+
}
25+
1926
initializer {
2027
PharmacyViewModel(pillulitoApplication().container.pharmacyRepository)
2128
}
@@ -30,6 +37,13 @@ object AppViewModelProvider {
3037
HistoryViewModel(pillulitoApplication().container.medicationRepository)
3138
}
3239

40+
initializer {
41+
SupervisorViewModel(
42+
pillulitoApplication().container.authRepository,
43+
pillulitoApplication().container.medicationRepository
44+
)
45+
}
46+
3347
initializer {
3448
val application =
3549
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY]

app/src/main/java/com/example/senpos/ui/components/TopBarComponent.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,7 @@ fun TopBarComponent(navController: NavHostController) {
3939

4040
Button(
4141
onClick = {
42-
43-
NotificationHelper.sendIntakeReminder(
44-
context,
45-
"Doliprane",
46-
"1000mg",
47-
123
48-
)
42+
navController.navigate(Route.Profile.route)
4943
},
5044

5145
colors = ButtonDefaults.buttonColors(containerColor = Color.White, contentColor = Color.Black)

app/src/main/java/com/example/senpos/ui/navigation/AppNavGraph.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import androidx.compose.runtime.Composable
44
import androidx.navigation.NavHostController
55
import androidx.navigation.compose.NavHost
66
import androidx.navigation.compose.composable
7+
import com.example.senpos.ui.screens.AccountInfoScreen
78
import com.example.senpos.ui.screens.AddPosologyScreen
89
import com.example.senpos.ui.screens.HistoryScreen
910
import com.example.senpos.ui.screens.LoginScreen
1011
import com.example.senpos.ui.screens.PharmacyMapScreen
1112
import com.example.senpos.ui.screens.SignupScreen
1213
import com.example.senpos.ui.screens.TodayScreen
14+
import com.example.senpos.ui.screens.SupervisorScreen
1315

1416
@Composable
1517
fun AppNavGraph(navController: NavHostController) {
@@ -40,5 +42,13 @@ fun AppNavGraph(navController: NavHostController) {
4042
composable(Route.PharmacyMap.route) {
4143
PharmacyMapScreen(navController)
4244
}
45+
46+
composable(Route.Supervisor.route) {
47+
SupervisorScreen(navController)
48+
}
49+
50+
composable(Route.Profile.route) {
51+
AccountInfoScreen(navController)
52+
}
4353
}
4454
}

app/src/main/java/com/example/senpos/ui/navigation/Routes.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ sealed class Route(val route: String) {
77
object Login: Route("login")
88
object Signup: Route("signup")
99
object PharmacyMap: Route("pharmacy_map")
10+
object Supervisor : Route("supervisor")
11+
object Profile : Route("profile")
1012
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package com.example.senpos.ui.screens
2+
3+
4+
import androidx.compose.foundation.background
5+
import androidx.compose.foundation.layout.*
6+
import androidx.compose.foundation.shape.RoundedCornerShape
7+
import androidx.compose.material3.*
8+
import androidx.compose.runtime.*
9+
import androidx.compose.ui.Alignment
10+
import androidx.compose.ui.Modifier
11+
import androidx.compose.ui.draw.clip
12+
import androidx.compose.ui.graphics.Color
13+
import androidx.compose.ui.text.font.FontWeight
14+
import androidx.compose.ui.unit.dp
15+
import androidx.compose.ui.unit.sp
16+
import androidx.lifecycle.viewmodel.compose.viewModel
17+
import androidx.navigation.NavHostController
18+
import com.example.senpos.ui.AppViewModelProvider
19+
import com.example.senpos.ui.components.NavBarComponent
20+
import com.example.senpos.ui.components.TopBarComponent
21+
import com.example.senpos.ui.navigation.Route
22+
import com.example.senpos.viewmodels.AccountInfoViewModel
23+
24+
private val Orange = Color(0xFFFF6C00)
25+
private val OrangeLight = Color(0xFFFFF3EC)
26+
private val CardBg = Color(0xFFFAFAFA)
27+
28+
@Composable
29+
fun AccountInfoScreen(
30+
navController: NavHostController,
31+
viewModel: AccountInfoViewModel = viewModel(factory = AppViewModelProvider.Factory)
32+
) {
33+
val uiState by viewModel.uiState.collectAsState()
34+
35+
Column(modifier = Modifier.fillMaxSize()) {
36+
TopBarComponent(navController)
37+
38+
Column(
39+
modifier = Modifier
40+
.weight(1f)
41+
.fillMaxWidth()
42+
.padding(20.dp),
43+
verticalArrangement = Arrangement.spacedBy(20.dp)
44+
) {
45+
Text(
46+
text = "My account",
47+
fontSize = 24.sp,
48+
fontWeight = FontWeight.Bold,
49+
color = Orange
50+
)
51+
52+
Card(
53+
shape = RoundedCornerShape(20.dp),
54+
colors = CardDefaults.cardColors(containerColor = CardBg),
55+
elevation = CardDefaults.cardElevation(0.dp),
56+
modifier = Modifier.fillMaxWidth()
57+
) {
58+
Column(
59+
modifier = Modifier.padding(20.dp),
60+
verticalArrangement = Arrangement.spacedBy(14.dp)
61+
) {
62+
InfoRow(label = "First name", value = uiState.firstName)
63+
InfoRow(label = "Last name", value = uiState.lastName)
64+
InfoRow(label = "Email", value = uiState.email)
65+
}
66+
}
67+
68+
Card(
69+
shape = RoundedCornerShape(20.dp),
70+
colors = CardDefaults.cardColors(containerColor = OrangeLight),
71+
elevation = CardDefaults.cardElevation(0.dp),
72+
modifier = Modifier.fillMaxWidth()
73+
) {
74+
Column(
75+
modifier = Modifier.padding(20.dp),
76+
horizontalAlignment = Alignment.CenterHorizontally,
77+
verticalArrangement = Arrangement.spacedBy(8.dp)
78+
) {
79+
Text(
80+
text = "Your link code",
81+
fontSize = 14.sp,
82+
color = Color(0xFF000000)
83+
)
84+
Text(
85+
text = uiState.linkCode,
86+
fontSize = 32.sp,
87+
fontWeight = FontWeight.Bold,
88+
color = Orange
89+
)
90+
Text(
91+
text = "Share this code with a family member so they can follow your medication.",
92+
fontSize = 13.sp,
93+
color = Color(0xFF000000),
94+
modifier = Modifier.padding(horizontal = 8.dp)
95+
)
96+
}
97+
}
98+
99+
Spacer(modifier = Modifier.weight(1f))
100+
101+
Button(
102+
onClick = {
103+
viewModel.logout()
104+
navController.navigate(Route.Login.route) {
105+
popUpTo(0) { inclusive = true }
106+
}
107+
},
108+
modifier = Modifier
109+
.fillMaxWidth()
110+
.height(56.dp),
111+
shape = RoundedCornerShape(16.dp),
112+
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFE53935))
113+
) {
114+
Text("Log out", fontSize = 16.sp, fontWeight = FontWeight.Bold)
115+
}
116+
117+
Spacer(modifier = Modifier.height(8.dp))
118+
}
119+
120+
NavBarComponent(navController)
121+
}
122+
}
123+
124+
@Composable
125+
private fun InfoRow(label: String, value: String) {
126+
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
127+
Text(label, fontSize = 13.sp, color = Color(0xFF888888))
128+
Text(value, fontSize = 17.sp, fontWeight = FontWeight.Medium, color = Color(0xFF222222))
129+
}
130+
}

0 commit comments

Comments
 (0)