Ai aanpassingen en slepen in planner blokken
This commit is contained in:
+144
-18
@@ -121,33 +121,45 @@ $categories = [
|
||||
<?php foreach ($categories as $catKey => $catConfig):
|
||||
$catCards = array_filter($cards, fn($c) => $c['category'] === $catKey);
|
||||
?>
|
||||
<div class="fociz-card p-4 flex flex-col min-h-[500px]">
|
||||
<div class="fociz-card p-4 flex flex-col min-h-[500px] transition-all duration-200">
|
||||
<!-- Column Header -->
|
||||
<div class="flex items-center justify-between pb-3 mb-3 border-b border-slate-100 dark:border-slate-800">
|
||||
<div class="flex items-center space-x-2">
|
||||
<i data-lucide="<?= $catConfig['icon'] ?>" class="w-4 h-4 text-<?= $catConfig['color'] ?>-500"></i>
|
||||
<h3 class="text-xs font-bold text-slate-900 dark:text-white uppercase tracking-wider"><?= $catConfig['title'] ?></h3>
|
||||
</div>
|
||||
<span class="text-xs font-mono font-bold px-2 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 border border-slate-200 dark:border-slate-700">
|
||||
<span id="badge-count-<?= htmlspecialchars(md5($catKey)) ?>" class="text-xs font-mono font-bold px-2 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 border border-slate-200 dark:border-slate-700">
|
||||
<?= count($catCards) ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Cards Container -->
|
||||
<div class="flex-1 space-y-3">
|
||||
<!-- Cards Container as Drop Zone -->
|
||||
<div
|
||||
class="brainstorm-lane flex-1 space-y-3 min-h-[140px] rounded-xl p-1.5 transition-all duration-150"
|
||||
data-category="<?= htmlspecialchars($catKey, ENT_QUOTES) ?>"
|
||||
ondragover="handleCanvasLaneDragOver(event)"
|
||||
ondragleave="handleCanvasLaneDragLeave(event)"
|
||||
ondrop="handleCanvasLaneDrop(event, '<?= htmlspecialchars($catKey, ENT_QUOTES) ?>')"
|
||||
>
|
||||
<?php if (empty($catCards)): ?>
|
||||
<div class="py-8 text-center text-slate-400 dark:text-slate-600 text-xs font-medium">
|
||||
<div class="lane-empty-placeholder py-8 text-center text-slate-400 dark:text-slate-600 text-xs font-medium pointer-events-none">
|
||||
Nog geen kaarten in deze categorie.
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($catCards as $card): ?>
|
||||
<div class="group relative rounded-xl p-4 border <?= $catConfig['border'] ?> <?= $catConfig['bg'] ?> backdrop-blur-sm shadow-2xs transition hover:-translate-y-0.5" id="card-<?= $card['id'] ?>">
|
||||
<div
|
||||
id="card-<?= $card['id'] ?>"
|
||||
draggable="true"
|
||||
ondragstart="handleCanvasCardDragStart(event, <?= $card['id'] ?>)"
|
||||
ondragend="handleCanvasCardDragEnd(event)"
|
||||
class="brainstorm-card group relative rounded-2xl p-4 border <?= $catConfig['border'] ?> <?= $catConfig['bg'] ?> backdrop-blur-sm shadow-sm hover:shadow-md transition-all duration-150 cursor-grab active:cursor-grabbing hover:-translate-y-0.5 flex flex-col justify-between"
|
||||
>
|
||||
|
||||
<!-- Top: Checkbox voor selectie + Roadmap badge -->
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<label class="flex items-center space-x-2 cursor-pointer">
|
||||
<div class="flex items-center justify-between gap-2 mb-2.5">
|
||||
<label class="inline-flex items-center space-x-2 cursor-pointer select-none">
|
||||
<input type="checkbox" value="<?= $card['id'] ?>" data-content="<?= htmlspecialchars($card['content'], ENT_QUOTES) ?>" class="card-checkbox w-4 h-4 rounded bg-white dark:bg-slate-900 border-slate-300 dark:border-slate-700 text-indigo-600 focus:ring-0">
|
||||
<span class="text-[10px] text-slate-500 dark:text-slate-400 font-medium">Selecteer</span>
|
||||
<span class="text-[11px] text-slate-500 dark:text-slate-400 font-medium">Selecteer</span>
|
||||
</label>
|
||||
|
||||
<?php if (!empty($card['converted_to_roadmap_item_id'])): ?>
|
||||
@@ -158,24 +170,26 @@ $categories = [
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Inhoud -->
|
||||
<p class="text-xs text-slate-800 dark:text-slate-200 leading-relaxed whitespace-pre-wrap font-medium">
|
||||
<?= htmlspecialchars($card['content']) ?>
|
||||
</p>
|
||||
<!-- Inhoud Post-it met verfijnde typografie en uitlijning -->
|
||||
<div class="text-left py-1">
|
||||
<p class="text-xs text-slate-800 dark:text-slate-100 font-medium leading-relaxed whitespace-pre-wrap break-words text-left">
|
||||
<?= htmlspecialchars($card['content']) ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Footer van kaart -->
|
||||
<div class="mt-3 pt-2.5 border-t border-slate-200/60 dark:border-slate-800/60 flex items-center justify-between text-[10px] text-slate-500 dark:text-slate-400">
|
||||
<div class="flex items-center space-x-1.5">
|
||||
<span><?= htmlspecialchars($card['author_name'] ?? 'Collega') ?></span>
|
||||
<div class="flex items-center space-x-1.5 min-w-0">
|
||||
<span class="truncate font-semibold text-slate-700 dark:text-slate-300"><?= htmlspecialchars($card['author_name'] ?? 'Collega') ?></span>
|
||||
<?php if ($aiSettings['ai_enabled'] && $aiSettings['has_key']): ?>
|
||||
<button onclick="openAiBreakdownModal(<?= $card['id'] ?>, <?= htmlspecialchars(json_encode($card['content']), ENT_QUOTES) ?>)" class="inline-flex items-center space-x-1 px-2 py-0.5 rounded-lg bg-violet-100/90 hover:bg-violet-200 dark:bg-violet-950/60 dark:hover:bg-violet-900/60 text-violet-700 dark:text-violet-300 font-bold text-[10px] transition cursor-pointer border border-violet-200/80 dark:border-violet-800/60 shadow-2xs" title="Splits dit idee uit naar behapbare taken via Google Gemini Pro">
|
||||
<button onclick="openAiBreakdownModal(<?= $card['id'] ?>, <?= htmlspecialchars(json_encode($card['content']), ENT_QUOTES) ?>)" class="inline-flex items-center space-x-1 px-2 py-0.5 rounded-lg bg-violet-100/90 hover:bg-violet-200 dark:bg-violet-950/60 dark:hover:bg-violet-900/60 text-violet-700 dark:text-violet-300 font-bold text-[10px] transition cursor-pointer border border-violet-200/80 dark:border-violet-800/60 shadow-2xs flex-shrink-0" title="Splits dit idee uit naar behapbare taken via Google Gemini Pro">
|
||||
<i data-lucide="sparkles" class="w-3 h-3 text-violet-500"></i>
|
||||
<span>Werk uit met AI</span>
|
||||
<span>AI</span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex items-center space-x-1.5 flex-shrink-0">
|
||||
<!-- Upvote button -->
|
||||
<button onclick="voteCard(<?= $card['id'] ?>)" class="flex items-center space-x-1 px-2 py-1 rounded-lg bg-white/80 hover:bg-white dark:bg-slate-800/80 dark:hover:bg-slate-700 text-slate-600 dark:text-slate-300 hover:text-amber-500 dark:hover:text-amber-400 border border-slate-200/80 dark:border-transparent transition shadow-xs cursor-pointer">
|
||||
<i data-lucide="thumbs-up" class="w-3 h-3"></i>
|
||||
@@ -550,6 +564,118 @@ async function deleteCard(cardId) {
|
||||
document.getElementById(`card-${cardId}`)?.remove();
|
||||
}
|
||||
|
||||
// --- Drag & Drop tussen Brainstorm Categorie Lanes ---
|
||||
let draggedCanvasCardId = null;
|
||||
|
||||
function handleCanvasCardDragStart(e, cardId) {
|
||||
draggedCanvasCardId = cardId;
|
||||
try {
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/plain', String(cardId));
|
||||
} catch (err) {}
|
||||
|
||||
setTimeout(() => {
|
||||
const el = document.getElementById(`card-${cardId}`);
|
||||
if (el) {
|
||||
el.classList.add('opacity-40', 'scale-[0.98]');
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function handleCanvasCardDragEnd(e) {
|
||||
if (draggedCanvasCardId) {
|
||||
const el = document.getElementById(`card-${draggedCanvasCardId}`);
|
||||
if (el) {
|
||||
el.classList.remove('opacity-40', 'scale-[0.98]');
|
||||
}
|
||||
draggedCanvasCardId = null;
|
||||
}
|
||||
|
||||
document.querySelectorAll('.brainstorm-lane').forEach(lane => {
|
||||
lane.classList.remove('bg-indigo-50/80', 'dark:bg-indigo-950/40', 'ring-2', 'ring-indigo-400', 'dark:ring-indigo-500', 'ring-inset');
|
||||
});
|
||||
}
|
||||
|
||||
function handleCanvasLaneDragOver(e) {
|
||||
if (!draggedCanvasCardId) return;
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
const lane = e.currentTarget;
|
||||
if (lane && !lane.classList.contains('ring-2')) {
|
||||
lane.classList.add('bg-indigo-50/80', 'dark:bg-indigo-950/40', 'ring-2', 'ring-indigo-400', 'dark:ring-indigo-500', 'ring-inset');
|
||||
}
|
||||
}
|
||||
|
||||
function handleCanvasLaneDragLeave(e) {
|
||||
const lane = e.currentTarget;
|
||||
if (lane && !lane.contains(e.relatedTarget)) {
|
||||
lane.classList.remove('bg-indigo-50/80', 'dark:bg-indigo-950/40', 'ring-2', 'ring-indigo-400', 'dark:ring-indigo-500', 'ring-inset');
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCanvasLaneDrop(e, targetCategory) {
|
||||
e.preventDefault();
|
||||
const lane = e.currentTarget;
|
||||
if (lane) {
|
||||
lane.classList.remove('bg-indigo-50/80', 'dark:bg-indigo-950/40', 'ring-2', 'ring-indigo-400', 'dark:ring-indigo-500', 'ring-inset');
|
||||
}
|
||||
|
||||
const cardId = draggedCanvasCardId || parseInt(e.dataTransfer.getData('text/plain'), 10);
|
||||
draggedCanvasCardId = null;
|
||||
|
||||
if (!cardId || !targetCategory) return;
|
||||
|
||||
const cardEl = document.getElementById(`card-${cardId}`);
|
||||
if (!cardEl) return;
|
||||
|
||||
const sourceLane = cardEl.closest('.brainstorm-lane');
|
||||
const sourceCategory = sourceLane ? sourceLane.getAttribute('data-category') : null;
|
||||
|
||||
// Als de kaart al in deze categorie zit, doe niets
|
||||
if (sourceCategory === targetCategory) return;
|
||||
|
||||
// Verplaats DOM element direct voor een directe, vloeiende UX
|
||||
lane.appendChild(cardEl);
|
||||
const placeholder = lane.querySelector('.lane-empty-placeholder');
|
||||
if (placeholder) placeholder.remove();
|
||||
|
||||
// Kleurstijlen per categorie bijwerken
|
||||
const categoryStyles = {
|
||||
'Ideeën': { border: 'border-amber-200/80', darkBorder: 'dark:border-amber-800/40', bg: 'bg-amber-50/60', darkBg: 'dark:bg-amber-950/20' },
|
||||
'Knelpunten': { border: 'border-rose-200/80', darkBorder: 'dark:border-rose-800/40', bg: 'bg-rose-50/60', darkBg: 'dark:bg-rose-950/20' },
|
||||
'Oplossingen': { border: 'border-teal-200/80', darkBorder: 'dark:border-teal-800/40', bg: 'bg-teal-50/60', darkBg: 'dark:bg-teal-950/20' },
|
||||
'Quick Wins': { border: 'border-indigo-200/80', darkBorder: 'dark:border-indigo-800/40', bg: 'bg-indigo-50/60', darkBg: 'dark:bg-indigo-950/20' }
|
||||
};
|
||||
|
||||
// Verwijder oude kleurklassen en voeg nieuwe toe
|
||||
Object.values(categoryStyles).forEach(st => {
|
||||
cardEl.classList.remove(st.border, st.darkBorder, st.bg, st.darkBg);
|
||||
});
|
||||
const targetStyle = categoryStyles[targetCategory] || categoryStyles['Ideeën'];
|
||||
cardEl.classList.add(targetStyle.border, targetStyle.darkBorder, targetStyle.bg, targetStyle.darkBg);
|
||||
|
||||
// Stuur POST naar backend om categorie en kleur te bewaren
|
||||
try {
|
||||
const res = await fetch('/api/brainstorm.php?action=move_card', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
card_id: cardId,
|
||||
category: targetCategory
|
||||
})
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!data.success) {
|
||||
alert(data.error || 'Kon kaart niet verplaatsen');
|
||||
location.reload();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Fout bij verplaatsen brainstormkaart:', err);
|
||||
alert('Netwerkfout bij verplaatsen');
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// --- Roadmap Conversie Logica ---
|
||||
function getSelectedCardIds() {
|
||||
const checkboxes = document.querySelectorAll('.card-checkbox:checked');
|
||||
|
||||
Reference in New Issue
Block a user