update
This commit is contained in:
@@ -1,33 +1,34 @@
|
||||
package de.haushalt.app
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MainScreen() {
|
||||
val navController = rememberNavController()
|
||||
val backStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = backStackEntry?.destination?.route
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
Column {
|
||||
Navigation()
|
||||
Subnavigation()
|
||||
}
|
||||
}
|
||||
topBar = { Breadcrumb(currentRoute = currentRoute, navController = navController) }
|
||||
) { innerPadding ->
|
||||
NavHost(
|
||||
navController = navController,
|
||||
@@ -39,20 +40,43 @@ fun MainScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun Navigation() {
|
||||
CenterAlignedTopAppBar(
|
||||
title = { Text("Haushalt") }
|
||||
private fun Breadcrumb(currentRoute: String?, navController: NavController) {
|
||||
// Trail: (route, label). Erweitert sich pro neuer Destination in späteren Modulen.
|
||||
val trail = listOf(
|
||||
"start" to "Haushalt",
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Subnavigation() {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(32.dp),
|
||||
color = MaterialTheme.colorScheme.surfaceVariant
|
||||
) {}
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
color = MaterialTheme.colorScheme.surfaceContainer
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.statusBarsPadding()
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
trail.forEachIndexed { index, (route, label) ->
|
||||
if (index > 0) {
|
||||
Text(
|
||||
text = "›",
|
||||
modifier = Modifier.padding(horizontal = 6.dp),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
val isCurrent = route == currentRoute
|
||||
Text(
|
||||
text = label,
|
||||
fontWeight = if (isCurrent) FontWeight.SemiBold else FontWeight.Normal,
|
||||
modifier = if (isCurrent) {
|
||||
Modifier
|
||||
} else {
|
||||
Modifier.clickable {
|
||||
navController.popBackStack(route, inclusive = false)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,33 @@
|
||||
<script setup>
|
||||
import { RouterView } from 'vue-router'
|
||||
import { computed } from 'vue'
|
||||
import { RouterView, RouterLink, useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const crumbs = computed(() => [
|
||||
{ label: 'Haushalt', to: '/' },
|
||||
...(route.meta.breadcrumb ?? []),
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header class="navigation">
|
||||
<header class="breadcrumb-bar">
|
||||
<div class="container">
|
||||
<span class="brand">Haushalt</span>
|
||||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||||
<template v-for="(crumb, i) in crumbs" :key="i">
|
||||
<span v-if="i > 0" class="sep">›</span>
|
||||
<RouterLink
|
||||
v-if="crumb.to && i < crumbs.length - 1"
|
||||
:to="crumb.to"
|
||||
class="crumb"
|
||||
>
|
||||
{{ crumb.label }}
|
||||
</RouterLink>
|
||||
<span v-else class="crumb current">{{ crumb.label }}</span>
|
||||
</template>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<nav class="subnavigation">
|
||||
<div class="container"></div>
|
||||
</nav>
|
||||
<main class="main-area">
|
||||
<div class="container">
|
||||
<RouterView />
|
||||
@@ -19,29 +36,40 @@ import { RouterView } from 'vue-router'
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.navigation {
|
||||
background: var(--nav-bg);
|
||||
.breadcrumb-bar {
|
||||
background: var(--breadcrumb-bg);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.navigation .container {
|
||||
.breadcrumb-bar .container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
.brand {
|
||||
font-size: 1.125rem;
|
||||
.breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
|
||||
.crumb {
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.crumb:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.crumb.current {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.subnavigation {
|
||||
background: var(--subnav-bg);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.subnavigation .container {
|
||||
height: 2rem;
|
||||
.sep {
|
||||
color: var(--text-muted);
|
||||
padding: 0 0.25rem;
|
||||
}
|
||||
|
||||
.main-area .container {
|
||||
|
||||
@@ -7,6 +7,7 @@ const router = createRouter({
|
||||
path: '/',
|
||||
name: 'start',
|
||||
component: () => import('../views/Startpage.vue'),
|
||||
meta: { breadcrumb: [] },
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
:root {
|
||||
--bg: #ffffff;
|
||||
--text: #1a1a1a;
|
||||
--text-muted: #6b7280;
|
||||
--border: #e5e5e5;
|
||||
--nav-bg: #f7f7f8;
|
||||
--subnav-bg: #f0f0f2;
|
||||
--breadcrumb-bg: #f7f7f8;
|
||||
color-scheme: light dark;
|
||||
}
|
||||
|
||||
|
||||
64
module.md
64
module.md
@@ -17,44 +17,62 @@ Implementierungs-Schritte als Feature-Module - WIE es gebaut wird
|
||||
## Backend
|
||||
- nothing
|
||||
## Frontend
|
||||
- App.vue - layout: navigation, subnavigation, main area
|
||||
- App.vue - layout: breadcrumb, main area
|
||||
- router - / start page route
|
||||
- Startpage.vue - start page
|
||||
- Startpage.vue - start page, no content
|
||||
## App
|
||||
- MainScreen.kt - layout: navigation, subnavigation, main area
|
||||
- StartScreen.kt - start page
|
||||
- MainScreen.kt - layout: breadcrumb, main area
|
||||
- StartScreen.kt - start page, no content
|
||||
## Features
|
||||
- Standard layout for all pages: navigation top, subnavigation below, main area
|
||||
- Start page as first instance, empty content
|
||||
- Standard layout for all pages: breadcrumb, main area
|
||||
|
||||
# Task module
|
||||
## Backend
|
||||
- Task - Task entity
|
||||
- id, name, date, status
|
||||
- id, name, date (due), status
|
||||
- TaskStatus - Enum for task status
|
||||
- active, done
|
||||
- active, done, inactive
|
||||
- TaskController - Task routes
|
||||
- index, show, create, update, delete, toggle
|
||||
- index, show, create, update, delete, toggle (active/done)
|
||||
- TaskManager - Task CRUD
|
||||
- create, update, delete, toggle
|
||||
- TaskRepository - Default task queries
|
||||
- TaskDto - Dto for create und update task
|
||||
- currentTasks()
|
||||
- TaskDto - Dto for create and update task
|
||||
## Frontend
|
||||
- route/index.js - /tasks tasks routing
|
||||
- Task.Vue - Display all tasks
|
||||
- TaskDetail.vue - Create and edit tasks
|
||||
- Startpage.vue - quader button for tasks
|
||||
- App.vue - register task routes in breadcrumb.
|
||||
- router - tasks routes /tasks, /tasks/all, /tasks/create, /tasks/:id
|
||||
- Task.vue
|
||||
- Display current tasks (now to +2 weeks and without date) as list with name (done strikethrough), onclick toggle status, order by date (no-date then date asc, hide inactive)
|
||||
- top right nav - list icon (all tasks), + icon (create), eye icon (toggle task visibility by active/done)
|
||||
- TaskAll.vue
|
||||
- Display all tasks as list with name (done strikethrough), pencil icon (edit), bin icon (delete), onclick toggle status, order by date (no-date then date asc then inactive asc)
|
||||
- top right nav - + icon (create)
|
||||
- TaskCreate.vue - Display form with name-text, date-date, status-select, save-button, abort-button
|
||||
- TaskEdit.vue
|
||||
- Display form with name-text, date-date, status-select, update-button, reset-button, abort-button, use current values
|
||||
- api.js - API routes to symfony
|
||||
## App
|
||||
- StartScreen.kt - quader button for tasks
|
||||
- MainScreen.kt - register task routes in breadcrumb.
|
||||
- NavHost - tasks routes /tasks, /tasks/all, /tasks/create, /tasks/:id
|
||||
- TaskScreen.kt
|
||||
- Display current tasks (now to +2 weeks and without date) as list with name (done strikethrough), onclick toggle status, order by date (no-date then date asc, hide inactive)
|
||||
- top right nav - list icon (all tasks), + icon (create), eye icon (toggle task visibility by active/done)
|
||||
- TaskAllScreen.kt
|
||||
- Display all tasks as list with name (done strikethrough), pencil icon (edit), bin icon (delete), onclick toggle status, order by date (no-date then date asc then inactive asc)
|
||||
- top right nav - + icon (create)
|
||||
- TaskCreateScreen.kt - Display form with name-text, date-date, status-select, save-button, abort-button
|
||||
- TaskEditScreen.kt
|
||||
- Display form with name-text, date-date, status-select, update-button, reset-button, abort-button, use current values
|
||||
- TaskApi.kt - API calls to symfony
|
||||
## Features
|
||||
- Task page
|
||||
- navigation - tasks
|
||||
- subnavigation - all tasks, new task, categories
|
||||
- Start page
|
||||
- main area - quader button to task page
|
||||
- Task page
|
||||
- main area - list all tasks, each task has name, status in badge, edit button, onclick toggle task status
|
||||
-
|
||||
- Task detal page
|
||||
- main area -
|
||||
- Start page: task button
|
||||
- Task page: current tasks ordered by date, filter done
|
||||
- TaskAll page: all tasks ordered by date and status, delete task
|
||||
- TaskCreate page: create task
|
||||
- TaskEdit page: update task
|
||||
|
||||
# Category module
|
||||
## Backend
|
||||
|
||||
Reference in New Issue
Block a user