visual prototyping
This commit is contained in:
@ -39,6 +39,7 @@ import com.tomhempel.rbarometer.questionnaire.QuestionnaireValidation
|
|||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import com.tomhempel.rbarometer.utils.ScreenLoading
|
import com.tomhempel.rbarometer.utils.ScreenLoading
|
||||||
import com.tomhempel.rbarometer.utils.ViewUtils
|
import com.tomhempel.rbarometer.utils.ViewUtils
|
||||||
@ -63,11 +64,15 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
private lateinit var sessionMetricClientsValue: TextView
|
private lateinit var sessionMetricClientsValue: TextView
|
||||||
private lateinit var sessionMetricMeasuresValue: TextView
|
private lateinit var sessionMetricMeasuresValue: TextView
|
||||||
private lateinit var sessionMetricSyncValue: TextView
|
private lateinit var sessionMetricSyncValue: TextView
|
||||||
|
private lateinit var todaySessionsTitle: TextView
|
||||||
|
private lateinit var todaySessionsSummary: TextView
|
||||||
|
private lateinit var todaySessionsContainer: LinearLayout
|
||||||
private lateinit var nextStepBannerCard: View
|
private lateinit var nextStepBannerCard: View
|
||||||
private lateinit var nextStepEyebrow: TextView
|
private lateinit var nextStepEyebrow: TextView
|
||||||
private lateinit var nextStepTitle: TextView
|
private lateinit var nextStepTitle: TextView
|
||||||
private lateinit var nextStepBody: TextView
|
private lateinit var nextStepBody: TextView
|
||||||
private lateinit var nextStepActionButton: MaterialButton
|
private lateinit var nextStepActionButton: MaterialButton
|
||||||
|
private lateinit var questionnaireListHost: View
|
||||||
private lateinit var questionnaireScroll: View
|
private lateinit var questionnaireScroll: View
|
||||||
private lateinit var buttonContainer: LinearLayout
|
private lateinit var buttonContainer: LinearLayout
|
||||||
private lateinit var bottomUploadDock: View
|
private lateinit var bottomUploadDock: View
|
||||||
@ -108,6 +113,65 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
UPLOAD,
|
UPLOAD,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class TodaySession(
|
||||||
|
val clientCode: String,
|
||||||
|
val status: String,
|
||||||
|
val cycle: Int,
|
||||||
|
val session: Int,
|
||||||
|
val totalSessions: Int,
|
||||||
|
val plannedDate: String,
|
||||||
|
val lastSession: String,
|
||||||
|
val nextSuggestedDate: String,
|
||||||
|
val measures: List<String>,
|
||||||
|
)
|
||||||
|
|
||||||
|
private val dummyTodaySessions = listOf(
|
||||||
|
TodaySession(
|
||||||
|
clientCode = "A102",
|
||||||
|
status = "Today",
|
||||||
|
cycle = 3,
|
||||||
|
session = 2,
|
||||||
|
totalSessions = 6,
|
||||||
|
plannedDate = "Today 14:00",
|
||||||
|
lastSession = "Jun 17",
|
||||||
|
nextSuggestedDate = "Jul 01",
|
||||||
|
measures = listOf("WHO-5", "Stress thermometer", "Relationship check"),
|
||||||
|
),
|
||||||
|
TodaySession(
|
||||||
|
clientCode = "B447",
|
||||||
|
status = "Overdue",
|
||||||
|
cycle = 1,
|
||||||
|
session = 5,
|
||||||
|
totalSessions = 6,
|
||||||
|
plannedDate = "Jun 18",
|
||||||
|
lastSession = "Jun 10",
|
||||||
|
nextSuggestedDate = "Jun 26",
|
||||||
|
measures = listOf("Mood check", "Goal tracking", "Counselor score review"),
|
||||||
|
),
|
||||||
|
TodaySession(
|
||||||
|
clientCode = "C083",
|
||||||
|
status = "Upcoming",
|
||||||
|
cycle = 2,
|
||||||
|
session = 1,
|
||||||
|
totalSessions = 6,
|
||||||
|
plannedDate = "Tomorrow",
|
||||||
|
lastSession = "Jun 21",
|
||||||
|
nextSuggestedDate = "Jul 08",
|
||||||
|
measures = listOf("Cycle baseline", "WHO-5", "Stress thermometer"),
|
||||||
|
),
|
||||||
|
TodaySession(
|
||||||
|
clientCode = "D219",
|
||||||
|
status = "Inactive",
|
||||||
|
cycle = 4,
|
||||||
|
session = 6,
|
||||||
|
totalSessions = 6,
|
||||||
|
plannedDate = "Not planned",
|
||||||
|
lastSession = "Jun 03",
|
||||||
|
nextSuggestedDate = "On hold",
|
||||||
|
measures = listOf("End-of-cycle review", "Participation status"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
private fun color(@ColorRes res: Int) = ContextCompat.getColor(activity, res)
|
private fun color(@ColorRes res: Int) = ContextCompat.getColor(activity, res)
|
||||||
|
|
||||||
private fun t(id: String) = LanguageManager.getText(languageID, id)
|
private fun t(id: String) = LanguageManager.getText(languageID, id)
|
||||||
@ -186,6 +250,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
|
|
||||||
bindViews()
|
bindViews()
|
||||||
loadQuestionnaireOrder()
|
loadQuestionnaireOrder()
|
||||||
|
renderTodaySessions()
|
||||||
createQuestionnaireButtons()
|
createQuestionnaireButtons()
|
||||||
setupCoachDisplay()
|
setupCoachDisplay()
|
||||||
setupLanguageSpinner()
|
setupLanguageSpinner()
|
||||||
@ -219,11 +284,15 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
sessionMetricClientsValue = activity.findViewById(R.id.sessionMetricClientsValue)
|
sessionMetricClientsValue = activity.findViewById(R.id.sessionMetricClientsValue)
|
||||||
sessionMetricMeasuresValue = activity.findViewById(R.id.sessionMetricMeasuresValue)
|
sessionMetricMeasuresValue = activity.findViewById(R.id.sessionMetricMeasuresValue)
|
||||||
sessionMetricSyncValue = activity.findViewById(R.id.sessionMetricSyncValue)
|
sessionMetricSyncValue = activity.findViewById(R.id.sessionMetricSyncValue)
|
||||||
|
todaySessionsTitle = activity.findViewById(R.id.todaySessionsTitle)
|
||||||
|
todaySessionsSummary = activity.findViewById(R.id.todaySessionsSummary)
|
||||||
|
todaySessionsContainer = activity.findViewById(R.id.todaySessionsContainer)
|
||||||
nextStepBannerCard = activity.findViewById(R.id.nextStepBannerCard)
|
nextStepBannerCard = activity.findViewById(R.id.nextStepBannerCard)
|
||||||
nextStepEyebrow = activity.findViewById(R.id.nextStepEyebrow)
|
nextStepEyebrow = activity.findViewById(R.id.nextStepEyebrow)
|
||||||
nextStepTitle = activity.findViewById(R.id.nextStepTitle)
|
nextStepTitle = activity.findViewById(R.id.nextStepTitle)
|
||||||
nextStepBody = activity.findViewById(R.id.nextStepBody)
|
nextStepBody = activity.findViewById(R.id.nextStepBody)
|
||||||
nextStepActionButton = activity.findViewById(R.id.nextStepActionButton)
|
nextStepActionButton = activity.findViewById(R.id.nextStepActionButton)
|
||||||
|
questionnaireListHost = activity.findViewById(R.id.questionnaireListHost)
|
||||||
questionnaireScroll = activity.findViewById(R.id.questionnaireScroll)
|
questionnaireScroll = activity.findViewById(R.id.questionnaireScroll)
|
||||||
bottomUploadDock = activity.findViewById(R.id.bottomUploadDock)
|
bottomUploadDock = activity.findViewById(R.id.bottomUploadDock)
|
||||||
questionnaireListLoading = activity.findViewById(R.id.questionnaireListLoading)
|
questionnaireListLoading = activity.findViewById(R.id.questionnaireListLoading)
|
||||||
@ -242,6 +311,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
textView.text = hubFallback("Sitzungsinstrumente", "Session measures")
|
textView.text = hubFallback("Sitzungsinstrumente", "Session measures")
|
||||||
applyHubLabels()
|
applyHubLabels()
|
||||||
updateSessionMetrics()
|
updateSessionMetrics()
|
||||||
|
renderTodaySessions()
|
||||||
applyCoachDisplay()
|
applyCoachDisplay()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +346,355 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renderTodaySessions() {
|
||||||
|
if (!::todaySessionsContainer.isInitialized) return
|
||||||
|
todaySessionsTitle.text = hubFallback("Sitzungen", "Sessions")
|
||||||
|
val dueCount = dummyTodaySessions.count { it.status == "Today" || it.status == "Overdue" }
|
||||||
|
todaySessionsSummary.text = "$dueCount today"
|
||||||
|
todaySessionsContainer.removeAllViews()
|
||||||
|
addSessionGroup(
|
||||||
|
title = hubFallback("Heute", "Today"),
|
||||||
|
sessions = dummyTodaySessions.filter { it.status == "Today" || it.status == "Overdue" },
|
||||||
|
)
|
||||||
|
addSessionGroup(
|
||||||
|
title = hubFallback("Demnächst", "Upcoming"),
|
||||||
|
sessions = dummyTodaySessions.filter { it.status == "Upcoming" },
|
||||||
|
)
|
||||||
|
addSessionGroup(
|
||||||
|
title = hubFallback("Inaktiv", "Inactive"),
|
||||||
|
sessions = dummyTodaySessions.filter { it.status == "Inactive" },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addSessionGroup(title: String, sessions: List<TodaySession>) {
|
||||||
|
if (sessions.isEmpty()) return
|
||||||
|
todaySessionsContainer.addView(TextView(activity).apply {
|
||||||
|
text = title
|
||||||
|
setPadding(dp(2), if (todaySessionsContainer.childCount == 0) 0 else dp(14), 0, dp(4))
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(R.color.brand_text_dark))
|
||||||
|
})
|
||||||
|
sessions.forEach { session ->
|
||||||
|
todaySessionsContainer.addView(createTodaySessionCard(session))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTodaySessionCard(session: TodaySession): View {
|
||||||
|
val card = MaterialCardView(activity).apply {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
).also {
|
||||||
|
it.setMargins(0, 0, 0, dp(10))
|
||||||
|
}
|
||||||
|
radius = dp(14).toFloat()
|
||||||
|
strokeWidth = dp(if (session.status == "Today") 2 else 1)
|
||||||
|
setStrokeColor(color(if (session.status == "Overdue") R.color.brand_chip_start_fill else R.color.brand_purple))
|
||||||
|
setCardBackgroundColor(color(R.color.brand_header_surface))
|
||||||
|
cardElevation = dp(2).toFloat()
|
||||||
|
}
|
||||||
|
val content = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
setPadding(dp(16), dp(14), dp(16), dp(14))
|
||||||
|
}
|
||||||
|
val header = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
gravity = Gravity.CENTER_VERTICAL
|
||||||
|
}
|
||||||
|
val titleBlock = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
|
}
|
||||||
|
titleBlock.addView(TextView(activity).apply {
|
||||||
|
text = session.clientCode
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(R.color.brand_text_dark))
|
||||||
|
})
|
||||||
|
titleBlock.addView(TextView(activity).apply {
|
||||||
|
text = "Cycle ${session.cycle} - Session ${session.session} of ${session.totalSessions}"
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
setTextColor(color(R.color.brand_text_muted))
|
||||||
|
})
|
||||||
|
header.addView(titleBlock)
|
||||||
|
header.addView(sessionStatusChip(session.status))
|
||||||
|
content.addView(header)
|
||||||
|
|
||||||
|
content.addView(TextView(activity).apply {
|
||||||
|
text = "Planned: ${session.plannedDate} Last: ${session.lastSession}"
|
||||||
|
setPadding(0, dp(10), 0, dp(8))
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
setTextColor(color(R.color.brand_text_dark))
|
||||||
|
})
|
||||||
|
content.addView(TextView(activity).apply {
|
||||||
|
text = hubFallback("Startet automatisch", "Starts automatically")
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(R.color.brand_text_muted))
|
||||||
|
})
|
||||||
|
session.measures.forEachIndexed { index, measure ->
|
||||||
|
content.addView(measureRow(measure, checked = index == 0))
|
||||||
|
}
|
||||||
|
content.addView(scheduleNextDateBlock(session.nextSuggestedDate))
|
||||||
|
|
||||||
|
val actions = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
setPadding(0, dp(12), 0, 0)
|
||||||
|
}
|
||||||
|
actions.addView(todayAction("Manage", filled = false, weight = 1f) {
|
||||||
|
showManageSessionSheet(session)
|
||||||
|
})
|
||||||
|
actions.addView(todayAction("Start session", filled = true, weight = 1.25f))
|
||||||
|
content.addView(actions)
|
||||||
|
card.addView(content)
|
||||||
|
return card
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sessionStatusChip(status: String): TextView =
|
||||||
|
TextView(activity).apply {
|
||||||
|
text = status
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(if (status == "Upcoming" || status == "Inactive") R.color.brand_chip_locked_text else R.color.brand_text_on_dark))
|
||||||
|
setBackgroundResource(
|
||||||
|
when (status) {
|
||||||
|
"Overdue" -> R.drawable.bg_chip_amber
|
||||||
|
"Upcoming", "Inactive" -> R.drawable.bg_chip_locked
|
||||||
|
else -> R.drawable.bg_chip_green
|
||||||
|
},
|
||||||
|
)
|
||||||
|
setPadding(dp(10), dp(6), dp(10), dp(6))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun measureRow(label: String, checked: Boolean): View =
|
||||||
|
LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
gravity = Gravity.CENTER_VERTICAL
|
||||||
|
setPadding(0, dp(7), 0, 0)
|
||||||
|
addView(TextView(activity).apply {
|
||||||
|
text = if (checked) "[x]" else "[ ]"
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(if (checked) R.color.brand_purple else R.color.brand_text_muted))
|
||||||
|
})
|
||||||
|
addView(TextView(activity).apply {
|
||||||
|
text = label
|
||||||
|
setPadding(dp(8), 0, 0, 0)
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
|
||||||
|
setTextColor(color(R.color.brand_text_dark))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleNextDateBlock(suggestedDate: String): View =
|
||||||
|
LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
background = ContextCompat.getDrawable(activity, R.drawable.bg_session_metric)
|
||||||
|
setPadding(dp(12), dp(10), dp(12), dp(10))
|
||||||
|
val lp = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
)
|
||||||
|
lp.setMargins(0, dp(12), 0, 0)
|
||||||
|
layoutParams = lp
|
||||||
|
addView(TextView(activity).apply {
|
||||||
|
text = hubFallback("Nächsten Termin planen", "Schedule next date")
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f)
|
||||||
|
setTextColor(color(R.color.brand_text_muted))
|
||||||
|
})
|
||||||
|
val row = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
gravity = Gravity.CENTER_VERTICAL
|
||||||
|
setPadding(0, dp(4), 0, 0)
|
||||||
|
}
|
||||||
|
row.addView(TextView(activity).apply {
|
||||||
|
text = suggestedDate
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(R.color.brand_text_dark))
|
||||||
|
})
|
||||||
|
row.addView(todayAction("Edit date", filled = false, weight = 0f, fixedWidth = dp(96)))
|
||||||
|
addView(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun todayAction(
|
||||||
|
label: String,
|
||||||
|
filled: Boolean,
|
||||||
|
weight: Float,
|
||||||
|
fixedWidth: Int? = null,
|
||||||
|
onClick: (() -> Unit)? = null,
|
||||||
|
): MaterialButton =
|
||||||
|
MaterialButton(activity).apply {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
|
fixedWidth ?: 0,
|
||||||
|
dp(40),
|
||||||
|
if (fixedWidth == null) weight else 0f,
|
||||||
|
).also { it.setMargins(0, 0, dp(8), 0) }
|
||||||
|
text = label
|
||||||
|
isAllCaps = false
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
|
||||||
|
cornerRadius = dp(18)
|
||||||
|
strokeWidth = dp(1)
|
||||||
|
insetTop = 0
|
||||||
|
insetBottom = 0
|
||||||
|
setTextColor(color(if (filled) R.color.brand_text_on_dark else R.color.brand_purple))
|
||||||
|
backgroundTintList = ColorStateList.valueOf(color(if (filled) R.color.brand_purple else R.color.brand_header_surface))
|
||||||
|
strokeColor = ColorStateList.valueOf(color(R.color.brand_purple))
|
||||||
|
setOnClickListener {
|
||||||
|
if (onClick != null) onClick()
|
||||||
|
else Toast.makeText(activity, "$label is prototype-only", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showManageSessionSheet(session: TodaySession) {
|
||||||
|
val container = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
setBackgroundColor(color(R.color.brand_surface))
|
||||||
|
setPadding(dp(20), dp(18), dp(20), dp(18))
|
||||||
|
}
|
||||||
|
|
||||||
|
val header = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
gravity = Gravity.CENTER_VERTICAL
|
||||||
|
}
|
||||||
|
val titleBlock = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
|
}
|
||||||
|
titleBlock.addView(TextView(activity).apply {
|
||||||
|
text = "Manage ${session.clientCode}"
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(R.color.brand_text_dark))
|
||||||
|
})
|
||||||
|
titleBlock.addView(TextView(activity).apply {
|
||||||
|
text = "Cycle ${session.cycle} - Session ${session.session} of ${session.totalSessions}"
|
||||||
|
setPadding(0, dp(3), 0, 0)
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
setTextColor(color(R.color.brand_text_muted))
|
||||||
|
})
|
||||||
|
val closeButton = MaterialButton(activity).apply {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(dp(78), dp(40))
|
||||||
|
text = "Close"
|
||||||
|
isAllCaps = false
|
||||||
|
cornerRadius = dp(18)
|
||||||
|
strokeWidth = dp(1)
|
||||||
|
insetTop = 0
|
||||||
|
insetBottom = 0
|
||||||
|
setTextColor(color(R.color.brand_purple))
|
||||||
|
backgroundTintList = ColorStateList.valueOf(color(R.color.brand_header_surface))
|
||||||
|
strokeColor = ColorStateList.valueOf(color(R.color.brand_header_stroke))
|
||||||
|
}
|
||||||
|
header.addView(titleBlock)
|
||||||
|
header.addView(closeButton)
|
||||||
|
|
||||||
|
val body = LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
setPadding(0, dp(14), 0, 0)
|
||||||
|
}
|
||||||
|
body.addView(manageSectionTitle("Client status"))
|
||||||
|
body.addView(LinearLayout(activity).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
addView(manageStatusButton("Active", selected = session.status != "Inactive"))
|
||||||
|
addView(manageStatusButton("Inactive", selected = session.status == "Inactive"))
|
||||||
|
addView(manageStatusButton("Archived", selected = false))
|
||||||
|
})
|
||||||
|
body.addView(manageSectionTitle("Scheduling"))
|
||||||
|
body.addView(manageAction("Edit next planned date", "Current suggestion: ${session.nextSuggestedDate}"))
|
||||||
|
body.addView(manageAction("Reschedule current session", "Move this session to another date"))
|
||||||
|
body.addView(manageAction("Skip this occurrence", "Keep the cycle but omit this planned visit"))
|
||||||
|
body.addView(manageSectionTitle("Session"))
|
||||||
|
body.addView(manageAction("View session protocol", "${session.measures.size} measures assigned"))
|
||||||
|
body.addView(manageAction("Add counselor note", "Attach a local note to this client"))
|
||||||
|
body.addView(manageAction("Sync client data", "Review pending local data for this client"))
|
||||||
|
body.addView(manageSectionTitle("Lifecycle"))
|
||||||
|
body.addView(manageAction("Mark no longer participating", "Move client to inactive"))
|
||||||
|
body.addView(manageAction("Archive client", "Hide from active scheduling"))
|
||||||
|
body.addView(manageAction("Delete client", "Prototype-only destructive option", destructive = true))
|
||||||
|
|
||||||
|
val scroll = ScrollView(activity).apply {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
dp(430),
|
||||||
|
)
|
||||||
|
isFillViewport = false
|
||||||
|
addView(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
container.addView(header)
|
||||||
|
container.addView(scroll)
|
||||||
|
|
||||||
|
val dialog = MaterialAlertDialogBuilder(activity)
|
||||||
|
.setView(container)
|
||||||
|
.create()
|
||||||
|
closeButton.setOnClickListener { dialog.dismiss() }
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun manageSectionTitle(title: String): View =
|
||||||
|
TextView(activity).apply {
|
||||||
|
text = title
|
||||||
|
setPadding(dp(2), dp(14), 0, dp(7))
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
|
||||||
|
setTypeface(typeface, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(color(R.color.brand_text_muted))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun manageStatusButton(label: String, selected: Boolean): MaterialButton =
|
||||||
|
MaterialButton(activity).apply {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, dp(40), 1f).also {
|
||||||
|
it.setMargins(0, 0, dp(8), 0)
|
||||||
|
}
|
||||||
|
text = label
|
||||||
|
isAllCaps = false
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
cornerRadius = dp(18)
|
||||||
|
strokeWidth = dp(1)
|
||||||
|
insetTop = 0
|
||||||
|
insetBottom = 0
|
||||||
|
setTextColor(color(if (selected) R.color.brand_text_on_dark else R.color.brand_text_dark))
|
||||||
|
backgroundTintList = ColorStateList.valueOf(
|
||||||
|
color(if (selected) R.color.brand_purple else R.color.brand_header_surface),
|
||||||
|
)
|
||||||
|
strokeColor = ColorStateList.valueOf(color(R.color.brand_purple))
|
||||||
|
setOnClickListener {
|
||||||
|
Toast.makeText(activity, "Set status to $label is prototype-only", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun manageAction(
|
||||||
|
title: String,
|
||||||
|
subtitle: String,
|
||||||
|
destructive: Boolean = false,
|
||||||
|
): View =
|
||||||
|
MaterialButton(activity).apply {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
).also { it.setMargins(0, 0, 0, dp(8)) }
|
||||||
|
text = "$title\n$subtitle"
|
||||||
|
isAllCaps = false
|
||||||
|
gravity = Gravity.START or Gravity.CENTER_VERTICAL
|
||||||
|
textAlignment = View.TEXT_ALIGNMENT_VIEW_START
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f)
|
||||||
|
cornerRadius = dp(16)
|
||||||
|
strokeWidth = dp(1)
|
||||||
|
insetTop = 0
|
||||||
|
insetBottom = 0
|
||||||
|
setPadding(dp(14), dp(11), dp(14), dp(11))
|
||||||
|
setTextColor(color(if (destructive) R.color.brand_destructive_text else R.color.brand_text_dark))
|
||||||
|
backgroundTintList = ColorStateList.valueOf(
|
||||||
|
color(if (destructive) R.color.brand_destructive_fill else R.color.brand_header_surface),
|
||||||
|
)
|
||||||
|
strokeColor = ColorStateList.valueOf(
|
||||||
|
color(if (destructive) R.color.brand_destructive_fill else R.color.brand_header_stroke),
|
||||||
|
)
|
||||||
|
setOnClickListener {
|
||||||
|
Toast.makeText(activity, "$title is prototype-only", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadQuestionnaireOrder() {
|
private fun loadQuestionnaireOrder() {
|
||||||
val serverItems = QuestionnaireCache.getQuestionnaireList(activity)
|
val serverItems = QuestionnaireCache.getQuestionnaireList(activity)
|
||||||
Log.d(TAG, "loadQuestionnaireOrder: serverItems from cache = ${serverItems.map { it.id }}")
|
Log.d(TAG, "loadQuestionnaireOrder: serverItems from cache = ${serverItems.map { it.id }}")
|
||||||
@ -765,11 +1184,11 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
val hasClients = assignedClientsForUi().isNotEmpty()
|
val hasClients = assignedClientsForUi().isNotEmpty()
|
||||||
if (hasClients) {
|
if (hasClients) {
|
||||||
noClientsAssignedText.visibility = View.GONE
|
noClientsAssignedText.visibility = View.GONE
|
||||||
textView.visibility = View.VISIBLE
|
textView.visibility = View.GONE
|
||||||
nextStepBannerCard.visibility = View.VISIBLE
|
nextStepBannerCard.visibility = View.GONE
|
||||||
questionnaireScroll.visibility = View.VISIBLE
|
questionnaireListHost.visibility = View.GONE
|
||||||
|
questionnaireScroll.visibility = View.GONE
|
||||||
bottomUploadDock.visibility = View.VISIBLE
|
bottomUploadDock.visibility = View.VISIBLE
|
||||||
updateNextStepBanner()
|
|
||||||
} else {
|
} else {
|
||||||
clearLoadedClientState()
|
clearLoadedClientState()
|
||||||
noClientsAssignedText.text = t("no_clients_assigned")
|
noClientsAssignedText.text = t("no_clients_assigned")
|
||||||
@ -777,6 +1196,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
textView.visibility = View.GONE
|
textView.visibility = View.GONE
|
||||||
updateSessionMetrics()
|
updateSessionMetrics()
|
||||||
nextStepBannerCard.visibility = View.GONE
|
nextStepBannerCard.visibility = View.GONE
|
||||||
|
questionnaireListHost.visibility = View.GONE
|
||||||
questionnaireScroll.visibility = View.GONE
|
questionnaireScroll.visibility = View.GONE
|
||||||
bottomUploadDock.visibility = View.GONE
|
bottomUploadDock.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@ -784,53 +1204,9 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
|
|
||||||
private fun updateNextStepBanner() {
|
private fun updateNextStepBanner() {
|
||||||
if (!::nextStepBannerCard.isInitialized) return
|
if (!::nextStepBannerCard.isInitialized) return
|
||||||
val total = dynamicButtons.size
|
|
||||||
if (total == 0) {
|
|
||||||
nextStepBannerCard.visibility = View.GONE
|
nextStepBannerCard.visibility = View.GONE
|
||||||
return
|
|
||||||
}
|
|
||||||
if (assignedClientsForUi().isEmpty()) return
|
|
||||||
|
|
||||||
nextStepBannerCard.visibility = View.VISIBLE
|
|
||||||
val completed = dynamicButtons.count { isCompleted(it) }
|
|
||||||
nextStepEyebrow.text = hubFallback("Nächster Sitzungsschritt", "Next session step")
|
|
||||||
nextStepTitle.text = hubFallback("Sitzungsstatus wird geprüft", "Checking session status")
|
|
||||||
nextStepBody.text = hubFallback("Lokale Daten, Reviews und Synchronisation werden ausgewertet.", "Reviewing local measures, scoring work, and sync status.")
|
|
||||||
nextStepActionButton.visibility = View.GONE
|
nextStepActionButton.visibility = View.GONE
|
||||||
nextStepActionButton.setOnClickListener(null)
|
nextStepActionButton.setOnClickListener(null)
|
||||||
|
|
||||||
nextStepJob?.cancel()
|
|
||||||
val clientCode = selectedClientCode
|
|
||||||
val token = TokenStore.getToken(activity)
|
|
||||||
nextStepJob = CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
val summary = withContext(Dispatchers.IO) { UnuploadedWorkRepository.summarize() }
|
|
||||||
val needsReview = withContext(Dispatchers.IO) {
|
|
||||||
if (clientCode.isBlank() || token.isNullOrBlank() || !TokenStore.isSessionValid(activity)) {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
ReviewScoresHandler.hasPendingReviewsForClient(activity, token, clientCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val action = when {
|
|
||||||
summary.pendingQuestionnaires > 0 || summary.pendingScoringReviews > 0 -> NextStepAction.UPLOAD
|
|
||||||
needsReview -> NextStepAction.REVIEW
|
|
||||||
completed < total && nextAvailableQuestionnaireButton() != null -> NextStepAction.QUESTIONNAIRE
|
|
||||||
else -> NextStepAction.NONE
|
|
||||||
}
|
|
||||||
val titleKey = when {
|
|
||||||
action == NextStepAction.UPLOAD -> "next_step_upload_title"
|
|
||||||
action == NextStepAction.REVIEW -> "next_step_review_title"
|
|
||||||
completed < total -> "next_step_questionnaire_title"
|
|
||||||
else -> "next_step_completed_title"
|
|
||||||
}
|
|
||||||
val bodyKey = when {
|
|
||||||
action == NextStepAction.UPLOAD -> "next_step_upload_body"
|
|
||||||
action == NextStepAction.REVIEW -> "next_step_review_body"
|
|
||||||
completed < total -> "next_step_questionnaire_body"
|
|
||||||
else -> "next_step_completed_body"
|
|
||||||
}
|
|
||||||
applyNextStepBanner(titleKey, bodyKey, action)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyNextStepBanner(titleKey: String, bodyKey: String, action: NextStepAction) {
|
private fun applyNextStepBanner(titleKey: String, bodyKey: String, action: NextStepAction) {
|
||||||
@ -1120,6 +1496,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
reviewScoresButton.text = t("review_scores")
|
reviewScoresButton.text = t("review_scores")
|
||||||
|
reviewScoresButton.visibility = View.GONE
|
||||||
uploadButton.text = t("upload")
|
uploadButton.text = t("upload")
|
||||||
applyHubLabels()
|
applyHubLabels()
|
||||||
applyCoachDisplay()
|
applyCoachDisplay()
|
||||||
@ -1230,6 +1607,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
|
|
||||||
private fun setupReviewScoresButton() {
|
private fun setupReviewScoresButton() {
|
||||||
reviewScoresButton.text = t("review_scores")
|
reviewScoresButton.text = t("review_scores")
|
||||||
|
reviewScoresButton.visibility = View.GONE
|
||||||
reviewScoresButton.setOnClickListener { openReviewScores() }
|
reviewScoresButton.setOnClickListener { openReviewScores() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1258,7 +1636,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupUploadButton() {
|
private fun setupUploadButton() {
|
||||||
reviewScoresButton.text = t("review_scores")
|
reviewScoresButton.visibility = View.GONE
|
||||||
uploadButton.text = t("upload")
|
uploadButton.text = t("upload")
|
||||||
uploadButton.setOnClickListener {
|
uploadButton.setOnClickListener {
|
||||||
TokenStore.ensureLegacyLoginTimestamp(activity)
|
TokenStore.ensureLegacyLoginTimestamp(activity)
|
||||||
|
|||||||
@ -176,6 +176,7 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -348,13 +349,73 @@
|
|||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/nextStepBannerCard" />
|
app:layout_constraintTop_toBottomOf="@id/todaySessionsSection" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/todaySessionsSection"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="18dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/bottomUploadDock"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sessionMetricsRow">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/todaySessionsTitle"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Today's sessions"
|
||||||
|
android:textColor="@color/brand_text_dark"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/todaySessionsSummary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_session_metric"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingTop="6dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
|
android:textColor="@color/brand_text_muted"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:scrollbars="none">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/todaySessionsContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/nextStepBannerCard"
|
android:id="@+id/nextStepBannerCard"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
|
android:visibility="gone"
|
||||||
app:cardBackgroundColor="@color/brand_emphasis_bg"
|
app:cardBackgroundColor="@color/brand_emphasis_bg"
|
||||||
app:cardCornerRadius="18dp"
|
app:cardCornerRadius="18dp"
|
||||||
app:cardElevation="3dp"
|
app:cardElevation="3dp"
|
||||||
@ -362,7 +423,7 @@
|
|||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/sessionMetricsRow">
|
app:layout_constraintTop_toBottomOf="@id/todaySessionsSection">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@ -46,12 +46,11 @@
|
|||||||
android:background="@drawable/bg_auth_logo">
|
android:background="@drawable/bg_auth_logo">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="28dp"
|
android:layout_width="36dp"
|
||||||
android:layout_height="28dp"
|
android:layout_height="36dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_person_24"
|
android:src="@drawable/ic_launcher_foreground" />
|
||||||
app:tint="@color/brand_purple" />
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|||||||
@ -181,6 +181,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="6dp"
|
android:layout_marginStart="6dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:visibility="gone"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -353,13 +354,73 @@
|
|||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/nextStepBannerCard" />
|
app:layout_constraintTop_toBottomOf="@id/todaySessionsSection" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/todaySessionsSection"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="18dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/bottomUploadDock"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/sessionMetricsRow">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/todaySessionsTitle"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Today's sessions"
|
||||||
|
android:textColor="@color/brand_text_dark"
|
||||||
|
android:textSize="22sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/todaySessionsSummary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_session_metric"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingTop="6dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
|
android:textColor="@color/brand_text_muted"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:scrollbars="none">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/todaySessionsContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/nextStepBannerCard"
|
android:id="@+id/nextStepBannerCard"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
|
android:visibility="gone"
|
||||||
app:cardBackgroundColor="@color/brand_emphasis_bg"
|
app:cardBackgroundColor="@color/brand_emphasis_bg"
|
||||||
app:cardCornerRadius="18dp"
|
app:cardCornerRadius="18dp"
|
||||||
app:cardElevation="3dp"
|
app:cardElevation="3dp"
|
||||||
@ -367,7 +428,7 @@
|
|||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/sessionMetricsRow">
|
app:layout_constraintTop_toBottomOf="@id/todaySessionsSection">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
Reference in New Issue
Block a user