Files
crm-system/app/webui/activities.html
T

221 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>CRM Activities</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="/css/app.css" />
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js"></script>
<script type="module" src="/js/store.js"></script>
<script type="module" src="/js/components/notifications.js"></script>
<script type="module" src="/components/activity-list.js"></script>
</head>
<body class="min-h-screen bg-slate-50">
<div x-data="toastContainer()" class="crm-toast-container" x-cloak>
<template x-for="n in items" :key="n.id">
<div class="crm-toast" :class="'toast-' + n.type"
@click="dismiss(n.id)" x-text="n.message"></div>
</template>
</div>
<div x-data="{ init: () => Alpine.store('auth').init() }" x-init="init()" class="flex min-h-screen">
<aside class="crm-sidebar">
<div class="px-6 py-4 text-white text-lg font-bold border-b border-slate-700">
<a href="/app.html" class="!text-white !border-0">CRM</a>
</div>
<nav class="mt-2">
<a href="/app.html">Dashboard</a>
<a href="/accounts.html">Accounts</a>
<a href="/contacts.html">Contacts</a>
<a href="/pipeline.html">Pipeline</a>
<a href="/activities.html" class="active">Activities</a>
<a href="/settings-profile.html">Profil</a>
<a href="/settings-users.html" x-show="$store.auth.isAdmin">Users (Admin)</a>
<a href="/settings-org.html" x-show="$store.auth.isAdmin">Org (Admin)</a>
</nav>
</aside>
<div class="flex-1 flex flex-col">
<header class="bg-white border-b border-slate-200 px-6 py-3 flex items-center justify-between">
<h1 class="text-xl font-semibold text-slate-800">Activities</h1>
<div class="flex items-center gap-3 text-sm">
<span class="text-slate-600">
<strong class="text-slate-900"
x-text="$store.auth.user ? $store.auth.user.name : '…'"></strong>
</span>
<button class="btn-secondary" @click="$store.auth.logout()">Logout</button>
</div>
</header>
<main class="flex-1 p-6" x-data="activityList()" x-init="init()">
<!-- Toolbar -->
<div class="crm-card mb-4 flex flex-wrap items-end gap-3">
<div>
<label class="crm-label">Typ</label>
<select x-model="type" class="crm-input">
<option value="">Alle</option>
<template x-for="t in types" :key="t">
<option :value="t" x-text="t"></option>
</template>
</select>
</div>
<div>
<label class="crm-label">Overdue</label>
<select x-model="overdue" class="crm-input">
<option value="">Alle</option>
<option value="true">Nur Overdue</option>
<option value="false">Nicht Overdue</option>
</select>
</div>
<div>
<label class="crm-label">Status</label>
<select x-model="completed" class="crm-input">
<option value="">Alle</option>
<option value="false">Offen</option>
<option value="true">Erledigt</option>
</select>
</div>
<button @click="applyFilters()" class="btn-primary">Filtern</button>
<button @click="openCreate()" class="btn-primary ml-auto">+ New Activity</button>
</div>
<!-- Loading -->
<div x-show="loading" class="crm-card text-center py-8">
<div class="crm-spinner mx-auto"></div>
<p class="text-slate-500 mt-2 text-sm">Lade Activities …</p>
</div>
<!-- Table -->
<div x-show="!loading" class="overflow-x-auto">
<table class="crm-table">
<thead>
<tr>
<th>Typ</th>
<th>Subject</th>
<th>Fällig</th>
<th>Owner</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<template x-for="a in activities" :key="a.id">
<tr class="cursor-pointer"
:class="{ 'row-overdue': isOverdue(a) }"
@click="openDetail(a)">
<td><span class="crm-badge" :class="typeBadge(a.type)" x-text="a.type"></span></td>
<td class="font-medium" x-text="a.subject"></td>
<td x-text="formatDateTime(a.due_date)"></td>
<td x-text="a.owner_id"></td>
<td>
<span x-show="isCompleted(a)" class="crm-badge badge-green">Erledigt</span>
<span x-show="!isCompleted(a) && isOverdue(a)" class="crm-badge badge-red">Overdue</span>
<span x-show="!isCompleted(a) && !isOverdue(a)" class="crm-badge badge-yellow">Offen</span>
</td>
</tr>
</template>
<tr x-show="!loading && activities.length === 0">
<td colspan="5" class="text-center text-slate-500 py-6">
Keine Activities gefunden.
</td>
</tr>
</tbody>
</table>
</div>
<!-- Pagination -->
<div class="flex items-center justify-between mt-4 text-sm text-slate-600"
x-show="!loading">
<span x-text="pageInfo"></span>
<div class="flex gap-2">
<button @click="prevPage()" :disabled="skip === 0" class="btn-secondary">← Zurück</button>
<button @click="nextPage()" :disabled="skip + limit >= total" class="btn-secondary">Weiter →</button>
</div>
</div>
<!-- Create modal -->
<div x-show="showCreate" x-cloak class="crm-modal-backdrop" @click.self="closeCreate()">
<div class="crm-modal p-6">
<h2 class="text-lg font-semibold mb-4">Neue Activity</h2>
<form @submit.prevent="submitCreate()">
<div class="grid grid-cols-2 gap-3 mb-3">
<div>
<label class="crm-label">Typ *</label>
<select x-model="createForm.type" class="crm-input" required>
<template x-for="t in types" :key="t">
<option :value="t" x-text="t"></option>
</template>
</select>
</div>
<div>
<label class="crm-label">Fällig am</label>
<input type="datetime-local"
x-model="createForm.due_date" class="crm-input" />
</div>
</div>
<div class="mb-3">
<label class="crm-label">Subject *</label>
<input type="text" required maxlength="255"
x-model="createForm.subject" class="crm-input" />
</div>
<div class="mb-3">
<label class="crm-label">Body</label>
<textarea x-model="createForm.body" class="crm-input" rows="2"></textarea>
</div>
<div class="text-xs text-slate-500 mb-3">
Polymorph-Parent: mindestens eine ID angeben.
</div>
<div class="grid grid-cols-3 gap-2 mb-3">
<div>
<label class="crm-label">Account-ID</label>
<input type="number" min="1" x-model="createForm.account_id" class="crm-input" />
</div>
<div>
<label class="crm-label">Contact-ID</label>
<input type="number" min="1" x-model="createForm.contact_id" class="crm-input" />
</div>
<div>
<label class="crm-label">Deal-ID</label>
<input type="number" min="1" x-model="createForm.deal_id" class="crm-input" />
</div>
</div>
<div x-show="createError" class="mb-3 p-2 bg-red-50 text-red-700 text-sm rounded"
x-text="createError"></div>
<div class="flex gap-2 justify-end">
<button type="button" @click="closeCreate()" class="btn-secondary">Abbrechen</button>
<button type="submit" :disabled="creating" class="btn-primary"
x-text="creating ? 'Speichere …' : 'Anlegen'"></button>
</div>
</form>
</div>
</div>
<!-- Detail modal -->
<div x-show="showDetail" x-cloak class="crm-modal-backdrop" @click.self="closeDetail()">
<div class="crm-modal p-6" x-show="selected">
<h2 class="text-lg font-semibold mb-2" x-text="selected?.subject"></h2>
<p class="text-xs text-slate-500 mb-3">
<span class="crm-badge" :class="typeBadge(selected?.type)" x-text="selected?.type"></span>
<span class="ml-2">Fällig: <span x-text="formatDateTime(selected?.due_date)"></span></span>
</p>
<p class="text-sm text-slate-700 mb-4" x-text="selected?.body || '(kein Body)'"></p>
<div class="flex gap-2 justify-end">
<button type="button" @click="closeDetail()" class="btn-secondary">Schließen</button>
<button x-show="!selected?.completed_at" @click="completeSelected()"
:disabled="completing" class="btn-primary"
x-text="completing ? 'Speichere …' : 'Als erledigt markieren'"></button>
</div>
</div>
</div>
</main>
</div>
</div>
</body>
</html>