Files
leocrm/app/webui/pipeline.html
T

168 lines
8.3 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 Pipeline</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/deal-kanban.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" class="active">Pipeline</a>
<a href="/activities.html">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">Pipeline</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="dealKanban()" x-init="init()">
<!-- Toolbar -->
<div class="flex items-center justify-between mb-4">
<div class="text-sm text-slate-600"
x-show="!loading">
Ziehe Karten zwischen Spalten, um die Stage zu ändern.
</div>
<div x-show="loading" class="crm-spinner"></div>
<div class="flex gap-2 items-center">
<input type="number" min="1" x-model="ownerId" placeholder="Owner-ID (optional)"
class="crm-input" style="width: 12rem;" />
<button @click="filterByOwner()" class="btn-secondary">Filtern</button>
<button @click="openCreate()" class="btn-primary">+ New Deal</button>
</div>
</div>
<div x-show="error" class="mb-4 p-3 bg-red-50 text-red-700 rounded text-sm"
x-text="error"></div>
<!-- Kanban board -->
<div class="crm-kanban">
<template x-for="stage in stages" :key="stage">
<div class="crm-kanban-col"
:class="{ 'drag-over': dragOverStage === stage }"
@dragover.prevent="onDragOver($event, stage)"
@dragleave="onDragLeave(stage)"
@drop="onDrop($event, stage)">
<div class="flex items-center justify-between mb-2 px-1">
<h3 class="font-semibold text-slate-700 text-sm" x-text="stageLabel(stage)"></h3>
<span class="crm-badge badge-gray text-xs" x-text="columnCount(stage)"></span>
</div>
<p class="text-xs text-slate-500 px-1 mb-2" x-text="columnValue(stage)"></p>
<template x-for="deal in (dealsByStage[stage] || [])" :key="deal.id">
<div class="crm-kanban-card"
draggable="true"
@dragstart="onDragStart($event, deal.id)">
<p class="font-medium text-slate-900" x-text="deal.title"></p>
<p class="text-xs text-slate-500 mt-1">
<span x-text="formatCurrency(deal.value)"></span>
</p>
<p class="text-xs text-slate-400 mt-1" x-show="deal.close_date">
Close: <span x-text="formatDate(deal.close_date)"></span>
</p>
</div>
</template>
<div x-show="columnCount(stage) === 0"
class="text-center text-xs text-slate-400 py-4">
Keine Deals
</div>
</div>
</template>
</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">Neuer Deal</h2>
<form @submit.prevent="submitCreate()">
<div class="mb-3">
<label class="crm-label">Titel *</label>
<input type="text" required maxlength="255"
x-model="createForm.title" class="crm-input" />
</div>
<div class="grid grid-cols-2 gap-3 mb-3">
<div>
<label class="crm-label">Wert (€)</label>
<input type="number" min="0" step="0.01"
x-model.number="createForm.value" class="crm-input" />
</div>
<div>
<label class="crm-label">Währung</label>
<input type="text" maxlength="3" minlength="3"
x-model="createForm.currency" class="crm-input" />
</div>
</div>
<div class="grid grid-cols-2 gap-3 mb-3">
<div>
<label class="crm-label">Stage</label>
<select x-model="createForm.stage" class="crm-input">
<template x-for="s in stages" :key="s">
<option :value="s" x-text="stageLabel(s)"></option>
</template>
</select>
</div>
<div>
<label class="crm-label">Account-ID *</label>
<input type="number" min="1" required
x-model="createForm.account_id" class="crm-input" />
</div>
</div>
<div class="mb-3">
<label class="crm-label">Close-Datum</label>
<input type="date" x-model="createForm.close_date" class="crm-input" />
</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>
</main>
</div>
</div>
</body>
</html>