new features

This commit is contained in:
Matthias Hochmeister
2026-03-23 18:43:30 +01:00
parent 202a658b8d
commit 1b13e4f89e
31 changed files with 1022 additions and 517 deletions

View File

@@ -3,7 +3,7 @@ import {
Box, Tab, Tabs, Typography, Table, TableBody, TableCell, TableContainer,
TableHead, TableRow, Paper, Chip, IconButton, Button, Dialog, DialogTitle,
DialogContent, DialogActions, TextField, MenuItem, Select, FormControl,
InputLabel, Collapse, Divider, CircularProgress,
InputLabel, Collapse, Divider, CircularProgress, FormControlLabel, Switch,
} from '@mui/material';
import {
Add as AddIcon, Delete as DeleteIcon, ExpandMore, ExpandLess,
@@ -216,7 +216,7 @@ function IssueRow({
</Typography>
)}
{canManage && (
{(canManage || isOwner) && (
<Box sx={{ display: 'flex', gap: 1, mb: 2, flexWrap: 'wrap' }}>
<FormControl size="small" sx={{ minWidth: 160 }}>
<InputLabel>Status</InputLabel>
@@ -232,19 +232,21 @@ function IssueRow({
<MenuItem value="abgelehnt">Abgelehnt</MenuItem>
</Select>
</FormControl>
<FormControl size="small" sx={{ minWidth: 140 }}>
<InputLabel>Priorität</InputLabel>
<Select
value={issue.prioritaet}
label="Priorität"
onChange={(e) => updateMut.mutate({ prioritaet: e.target.value as Issue['prioritaet'] })}
onClick={(e) => e.stopPropagation()}
>
<MenuItem value="niedrig">Niedrig</MenuItem>
<MenuItem value="mittel">Mittel</MenuItem>
<MenuItem value="hoch">Hoch</MenuItem>
</Select>
</FormControl>
{canManage && (
<FormControl size="small" sx={{ minWidth: 140 }}>
<InputLabel>Priorität</InputLabel>
<Select
value={issue.prioritaet}
label="Priorität"
onChange={(e) => updateMut.mutate({ prioritaet: e.target.value as Issue['prioritaet'] })}
onClick={(e) => e.stopPropagation()}
>
<MenuItem value="niedrig">Niedrig</MenuItem>
<MenuItem value="mittel">Mittel</MenuItem>
<MenuItem value="hoch">Hoch</MenuItem>
</Select>
</FormControl>
)}
</Box>
)}
@@ -328,9 +330,6 @@ function IssueTable({ issues, canManage, userId }: { issues: Issue[]; canManage:
export default function Issues() {
const [searchParams, setSearchParams] = useSearchParams();
const tabParam = parseInt(searchParams.get('tab') || '0', 10);
const tab = isNaN(tabParam) || tabParam < 0 || tabParam > 1 ? 0 : tabParam;
const { showSuccess, showError } = useNotification();
const { hasPermission } = usePermissionContext();
const { user } = useAuth();
@@ -341,6 +340,11 @@ export default function Issues() {
const canCreate = hasPermission('issues:create');
const userId = user?.id || '';
const tabParam = parseInt(searchParams.get('tab') || '0', 10);
const maxTab = canManage ? 2 : (canViewAll ? 1 : 0);
const tab = isNaN(tabParam) || tabParam < 0 || tabParam > maxTab ? 0 : tabParam;
const [showDone, setShowDone] = useState(false);
const [createOpen, setCreateOpen] = useState(false);
const [form, setForm] = useState<CreateIssuePayload>({ titel: '', typ: 'bug', prioritaet: 'mittel' });
@@ -365,6 +369,8 @@ export default function Issues() {
};
const myIssues = issues.filter((i: Issue) => i.erstellt_von === userId);
const myIssuesFiltered = myIssues.filter((i: Issue) => showDone || (i.status !== 'erledigt' && i.status !== 'abgelehnt'));
const doneIssues = issues.filter((i: Issue) => i.status === 'erledigt' || i.status === 'abgelehnt');
return (
<DashboardLayout>
@@ -374,15 +380,21 @@ export default function Issues() {
<Tabs value={tab} onChange={handleTabChange} sx={{ mb: 0 }}>
<Tab label="Meine Issues" />
{canViewAll && <Tab label="Alle Issues" />}
{canManage && <Tab label="Erledigte Issues" />}
</Tabs>
<TabPanel value={tab} index={0}>
<FormControlLabel
control={<Switch checked={showDone} onChange={(e) => setShowDone(e.target.checked)} size="small" />}
label="Erledigte anzeigen"
sx={{ mb: 1 }}
/>
{isLoading ? (
<Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
<CircularProgress />
</Box>
) : (
<IssueTable issues={myIssues} canManage={canManage} userId={userId} />
<IssueTable issues={myIssuesFiltered} canManage={canManage} userId={userId} />
)}
</TabPanel>
@@ -397,6 +409,18 @@ export default function Issues() {
)}
</TabPanel>
)}
{canManage && (
<TabPanel value={tab} index={canViewAll ? 2 : 1}>
{isLoading ? (
<Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
<CircularProgress />
</Box>
) : (
<IssueTable issues={doneIssues} canManage={canManage} userId={userId} />
)}
</TabPanel>
)}
</Box>
{/* Create Issue Dialog */}