feat: Vorlagen-Ansicht (Admin) + Typ Vorlage in Projektseite
- neuer Typ Vorlage (nur Admin waehlbar), Badge, isTemplate - Dropdown-Filter Vorlagen nur fuer Admins; Vorlagen aus normalen Ansichten ausgeblendet - in Vorlagen-Ansicht: Vorlagen sehen + previewen Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9,10 +9,12 @@ import {
|
||||
FaGlobe,
|
||||
FaLock,
|
||||
FaCircleInfo,
|
||||
FaClone,
|
||||
} from 'react-icons/fa6'
|
||||
import { useWebsiteProjects } from '../hooks/useWebsiteProjects'
|
||||
import { useCustomers } from '../hooks/useCustomers'
|
||||
import { useWorkorders } from '../hooks/useWorkorders'
|
||||
import { useAuth } from '../context/AuthContext'
|
||||
import {
|
||||
createProjectFromTemplate,
|
||||
syncGiteaRepos,
|
||||
@@ -49,6 +51,14 @@ const TYPES = {
|
||||
icon: <FaGlobe />,
|
||||
hint: 'Oeffentlich erreichbar ohne Login unter <subdomain>.project.webklar.com',
|
||||
},
|
||||
template: {
|
||||
label: 'Vorlage',
|
||||
short: 'Vorlage',
|
||||
badge: 'badge-warn',
|
||||
icon: <FaClone />,
|
||||
hint: 'Website-Vorlage (login-geschuetzt) - erscheint nur fuer Admins in der Vorlagen-Ansicht',
|
||||
adminOnly: true,
|
||||
},
|
||||
project: {
|
||||
label: 'Internes Projekt (kein Hosting)',
|
||||
short: 'Projekt',
|
||||
@@ -59,6 +69,7 @@ const TYPES = {
|
||||
}
|
||||
|
||||
function typeOf(project) {
|
||||
if (project.isTemplate) return 'template'
|
||||
if (project.isPublic) return 'website'
|
||||
if (project.subdomain) return 'preview'
|
||||
return 'project'
|
||||
@@ -68,6 +79,7 @@ export default function ProjectsPage() {
|
||||
const { projects, loading, error, fetchAllProjects, assignProjects, unassignProject } = useWebsiteProjects()
|
||||
const { customers } = useCustomers()
|
||||
const { workorders } = useWorkorders(WORKORDER_FILTERS)
|
||||
const { isAdmin } = useAuth()
|
||||
const [filter, setFilter] = useState('all')
|
||||
const [showCreateModal, setShowCreateModal] = useState(false)
|
||||
const [createForm, setCreateForm] = useState({
|
||||
@@ -110,18 +122,21 @@ export default function ProjectsPage() {
|
||||
}, [workorders])
|
||||
|
||||
const counts = useMemo(() => {
|
||||
const active = projects.filter((p) => !p.archived)
|
||||
// Vorlagen sind aus den normalen Ansichten ausgeblendet (eigene Ansicht, nur Admin)
|
||||
const active = projects.filter((p) => !p.archived && !p.isTemplate)
|
||||
return {
|
||||
all: active.length,
|
||||
unassigned: active.filter((p) => !p.customerId).length,
|
||||
assigned: active.filter((p) => Boolean(p.customerId)).length,
|
||||
archived: projects.filter((p) => p.archived).length,
|
||||
templates: projects.filter((p) => p.isTemplate && !p.archived).length,
|
||||
}
|
||||
}, [projects])
|
||||
|
||||
const filteredProjects = useMemo(() => {
|
||||
if (filter === 'templates') return projects.filter((p) => p.isTemplate && !p.archived)
|
||||
if (filter === 'archived') return projects.filter((p) => p.archived)
|
||||
const active = projects.filter((p) => !p.archived)
|
||||
const active = projects.filter((p) => !p.archived && !p.isTemplate)
|
||||
if (filter === 'unassigned') return active.filter((p) => !p.customerId)
|
||||
if (filter === 'assigned') return active.filter((p) => Boolean(p.customerId))
|
||||
return active
|
||||
@@ -245,9 +260,14 @@ export default function ProjectsPage() {
|
||||
{ value: 'all', label: `Alle Projekte (${counts.all})` },
|
||||
{ value: 'unassigned', label: `Unzugeordnet (${counts.unassigned})` },
|
||||
{ value: 'assigned', label: `Zugeordnet (${counts.assigned})` },
|
||||
// Vorlagen-Ansicht nur fuer Admins
|
||||
...(isAdmin ? [{ value: 'templates', label: `Vorlagen (${counts.templates})` }] : []),
|
||||
{ value: 'archived', label: `Archiviert (${counts.archived})` },
|
||||
]
|
||||
|
||||
// Typ-Optionen im Bearbeiten-Modal: adminOnly-Typen (Vorlage) nur fuer Admins
|
||||
const typeOptions = Object.entries(TYPES).filter(([, meta]) => isAdmin || !meta.adminOnly)
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<header className="text-center mb-2">
|
||||
@@ -488,7 +508,7 @@ export default function ProjectsPage() {
|
||||
value={editForm.projectType}
|
||||
onChange={(e) => setEditForm((p) => ({ ...p, projectType: e.target.value }))}
|
||||
>
|
||||
{Object.entries(TYPES).map(([key, meta]) => (
|
||||
{typeOptions.map(([key, meta]) => (
|
||||
<option key={key} value={key}>{meta.label}</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
Reference in New Issue
Block a user