Brainstorm huge refactor
This commit is contained in:
+46
-3
@@ -647,15 +647,18 @@ function fociz_ai_categorize_cards(string $sessionTitle, string $theme, array $c
|
||||
/**
|
||||
* Genereert nieuwe relevante brainstorm ideeën voor een sessie
|
||||
*/
|
||||
function fociz_ai_generate_ideas(string $sessionTitle, string $theme, int $count = 4, ?int $userId = null): array {
|
||||
function fociz_ai_generate_ideas(string $sessionTitle, string $theme, int $count = 4, ?int $userId = null, string $description = ''): array {
|
||||
$descContext = !empty($description) ? "\nContext en briefing van de sessie:\n" . trim($description) . "\n" : "";
|
||||
|
||||
$systemPrompt = "Je bent een innovatieve productstrateeg en brainstorm co-pilot.\n"
|
||||
. "Genereer {$count} creatieve, scherpe en direct toepasbare ideeën voor een brainstormsessie getiteld: '{$sessionTitle}' (Thema: '{$theme}').\n"
|
||||
. "Houd de teksten beknopt en krachtig (1-2 zinnen per idee, alsof ze op een gele post-it staan).\n"
|
||||
. $descContext
|
||||
. "Houd de teksten beknopt en krachtig (1-2 zinnen per idee, alsof ze op een post-it staan).\n"
|
||||
. "Retourneer uitsluitend een JSON-object met het veld 'ideas' dat een array van strings is.";
|
||||
|
||||
$aiRes = fociz_ai_chat([
|
||||
['role' => 'system', 'content' => $systemPrompt],
|
||||
['role' => 'user', 'content' => "Genereer {$count} vernieuwende ideeën."],
|
||||
['role' => 'user', 'content' => "Genereer {$count} vernieuwende ideeën op basis van de sessie en context."],
|
||||
], ['json_mode' => true, 'user_id' => $userId]);
|
||||
|
||||
if (!$aiRes['success'] || empty($aiRes['json']['ideas'])) {
|
||||
@@ -665,6 +668,46 @@ function fociz_ai_generate_ideas(string $sessionTitle, string $theme, int $count
|
||||
return ['success' => true, 'ideas' => $aiRes['json']['ideas']];
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyseert de volledige sessie briefing en genereert een complete set post-its verdeeld over:
|
||||
* - Ideeën & Concepten (amber)
|
||||
* - Knelpunten & Uitdagingen (rose)
|
||||
* - Oplossingen & Features (teal)
|
||||
* - Quick Wins (indigo)
|
||||
*/
|
||||
function fociz_ai_generate_session_board(string $sessionTitle, string $theme, string $description = '', ?int $userId = null): array {
|
||||
$descContext = !empty($description)
|
||||
? "Uitgebreide sessiebeschrijving en briefing:\n" . trim($description) . "\n\n"
|
||||
: "Geen aanvullende briefing opgegeven; baseer je op de titel en het thema.\n\n";
|
||||
|
||||
$systemPrompt = "Je bent een ervaren agile facilitator en strategisch adviseur.\n"
|
||||
. "Je analyseert de briefing van een brainstormsessie getiteld '{$sessionTitle}' (Thema: '{$theme}').\n"
|
||||
. $descContext
|
||||
. "Jouw taak is om de sessie direct uit te werken tot een rijk, concreet whiteboard met post-its over exact 4 categorieën:\n"
|
||||
. "1. 'Ideeën': Vernieuwende concepten, functionaliteiten en strategische kansen (2 tot 4 post-its).\n"
|
||||
. "2. 'Knelpunten': Concreet benoemde knelpunten, risico's, blokkades of gebruikersfrustraties (2 tot 4 post-its).\n"
|
||||
. "3. 'Oplossingen': Structurele oplossingen, architectuurkeuzes of procesaanpassingen voor de knelpunten (2 tot 4 post-its).\n"
|
||||
. "4. 'Quick Wins': Laagdrempelige acties die met minimale inspanning direct resultaat opleveren (2 tot 3 post-its).\n\n"
|
||||
. "Regels per post-it:\n"
|
||||
. "- Formuleer scherp, helder en direct to-the-point (1-2 zinnen per kaartje alsof het op een fysieke post-it staat).\n"
|
||||
. "- Sluit naadloos aan op de verstrekte briefing en achtergrondinformatie.\n\n"
|
||||
. "Retourneer UITSLUITEND een geldig JSON-object met het veld 'cards', waarbij elk item bestaat uit:\n"
|
||||
. "- 'content': string (de tekst op de post-it)\n"
|
||||
. "- 'category': exact één van ['Ideeën', 'Knelpunten', 'Oplossingen', 'Quick Wins']";
|
||||
|
||||
$aiRes = fociz_ai_chat([
|
||||
['role' => 'system', 'content' => $systemPrompt],
|
||||
['role' => 'user', 'content' => "Genereer het complete brainstorm whiteboard op basis van de sessiebeschrijving."],
|
||||
], ['json_mode' => true, 'user_id' => $userId]);
|
||||
|
||||
if (!$aiRes['success'] || empty($aiRes['json']['cards']) || !is_array($aiRes['json']['cards'])) {
|
||||
// Fallback als Gemini geen gestructureerde cards array teruggaf
|
||||
return ['success' => false, 'error' => $aiRes['error'] ?? 'Kon geen gestructureerde post-its genereren'];
|
||||
}
|
||||
|
||||
return ['success' => true, 'cards' => $aiRes['json']['cards']];
|
||||
}
|
||||
|
||||
/**
|
||||
* Zet brainstorm kaartjes om in een scherp Roadmap Item
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
/**
|
||||
* Fociz Board & Timeline Integratie Helper
|
||||
* Biedt functies om taken / e-mails / Jira tickets direct als kaarten toe te voegen aan Kanban-borden en Project Tijdlijnen.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/auth.php';
|
||||
|
||||
/**
|
||||
* Haalt alle actieve borden op waar de gebruiker toegang toe heeft, inclusief kolommen (lanes).
|
||||
*/
|
||||
function fociz_get_user_boards_with_lanes(PDO $db, int $userId, bool $isAdmin): array {
|
||||
if ($isAdmin) {
|
||||
$stmt = $db->query("
|
||||
SELECT b.id, b.title, b.description, b.created_by_id
|
||||
FROM boards b
|
||||
WHERE b.is_archived = 0
|
||||
ORDER BY b.id ASC
|
||||
");
|
||||
$boards = $stmt->fetchAll();
|
||||
} else {
|
||||
$stmt = $db->prepare("
|
||||
SELECT b.id, b.title, b.description, b.created_by_id
|
||||
FROM boards b
|
||||
JOIN board_members bm ON b.id = bm.board_id
|
||||
WHERE bm.user_id = ? AND b.is_archived = 0
|
||||
ORDER BY b.id ASC
|
||||
");
|
||||
$stmt->execute([$userId]);
|
||||
$boards = $stmt->fetchAll();
|
||||
}
|
||||
|
||||
if (empty($boards)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$boardIds = array_map(fn($b) => (int)$b['id'], $boards);
|
||||
$placeholders = implode(',', array_fill(0, count($boardIds), '?'));
|
||||
|
||||
$laneStmt = $db->prepare("
|
||||
SELECT id, board_id, title, color, position
|
||||
FROM board_lanes
|
||||
WHERE board_id IN ({$placeholders})
|
||||
ORDER BY position ASC, id ASC
|
||||
");
|
||||
$laneStmt->execute($boardIds);
|
||||
$lanes = $laneStmt->fetchAll();
|
||||
|
||||
$lanesByBoard = [];
|
||||
foreach ($lanes as $lane) {
|
||||
$bId = (int)$lane['board_id'];
|
||||
$lanesByBoard[$bId][] = $lane;
|
||||
}
|
||||
|
||||
foreach ($boards as &$b) {
|
||||
$bId = (int)$b['id'];
|
||||
$b['lanes'] = $lanesByBoard[$bId] ?? [];
|
||||
}
|
||||
unset($b);
|
||||
|
||||
return $boards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Voegt een item toe aan een Kanban bord en optioneel aan de Project Tijdlijn.
|
||||
*
|
||||
* @param PDO $db Database verbinding
|
||||
* @param int $userId ID van de gebruiker
|
||||
* @param bool $isAdmin Is gebruiker admin
|
||||
* @param array $data Data array met:
|
||||
* - board_id (int)
|
||||
* - lane_id (int, optioneel - defaults naar 1e lane)
|
||||
* - title (string)
|
||||
* - description (string, optioneel)
|
||||
* - priority ('P1'|'P2'|'P3', optioneel)
|
||||
* - color (string, optioneel)
|
||||
* - schedule_on_timeline (bool, optioneel)
|
||||
* - start_date (string 'YYYY-MM-DD', optioneel)
|
||||
* - end_date (string 'YYYY-MM-DD', optioneel)
|
||||
* - start_time (string 'HH:MM', optioneel)
|
||||
* - end_time (string 'HH:MM', optioneel)
|
||||
* - sync_outlook (bool, optioneel)
|
||||
* @return array ['success' => bool, 'card_id' => int, 'message' => string]
|
||||
*/
|
||||
function fociz_add_item_to_board_and_timeline(PDO $db, int $userId, bool $isAdmin, array $data): array {
|
||||
$boardId = (int)($data['board_id'] ?? 0);
|
||||
$title = trim($data['title'] ?? '');
|
||||
if ($boardId <= 0 || empty($title)) {
|
||||
return ['success' => false, 'error' => 'Geldig bord en titel zijn verplicht.'];
|
||||
}
|
||||
|
||||
// Autorisatiecheck
|
||||
if (!$isAdmin) {
|
||||
$stmtCheck = $db->prepare("SELECT COUNT(*) FROM board_members WHERE board_id = ? AND user_id = ?");
|
||||
$stmtCheck->execute([$boardId, $userId]);
|
||||
if ((int)$stmtCheck->fetchColumn() === 0) {
|
||||
return ['success' => false, 'error' => 'Geen toegang tot dit bord.'];
|
||||
}
|
||||
}
|
||||
|
||||
$laneId = (int)($data['lane_id'] ?? 0);
|
||||
if ($laneId <= 0) {
|
||||
$stmtLane = $db->prepare("SELECT id FROM board_lanes WHERE board_id = ? ORDER BY position ASC, id ASC LIMIT 1");
|
||||
$stmtLane->execute([$boardId]);
|
||||
$laneId = (int)$stmtLane->fetchColumn();
|
||||
}
|
||||
|
||||
if ($laneId <= 0) {
|
||||
return ['success' => false, 'error' => 'Het geselecteerde bord heeft geen kolommen.'];
|
||||
}
|
||||
|
||||
$description = trim($data['description'] ?? '');
|
||||
$priority = in_array($data['priority'] ?? '', ['P1', 'P2', 'P3']) ? $data['priority'] : 'P2';
|
||||
$color = in_array($data['color'] ?? '', ['yellow', 'blue', 'green', 'purple', 'pink', 'orange', 'slate', 'indigo']) ? $data['color'] : 'blue';
|
||||
|
||||
$stmtMax = $db->prepare("SELECT COALESCE(MAX(position), -1) FROM board_cards WHERE lane_id = ?");
|
||||
$stmtMax->execute([$laneId]);
|
||||
$maxPos = (int)$stmtMax->fetchColumn();
|
||||
|
||||
$stmtInsert = $db->prepare("
|
||||
INSERT INTO board_cards (board_id, lane_id, title, description, assignee_id, priority, color, position, created_by_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
$stmtInsert->execute([$boardId, $laneId, $title, $description, $userId, $priority, $color, $maxPos + 1, $userId]);
|
||||
$cardId = (int)$db->lastInsertId();
|
||||
|
||||
// Optioneel inplannen op Tijdlijn / Gantt
|
||||
$scheduleOnTimeline = !empty($data['schedule_on_timeline']);
|
||||
if ($scheduleOnTimeline && $cardId > 0) {
|
||||
$startDate = !empty($data['start_date']) ? trim($data['start_date']) : date('Y-m-d');
|
||||
$endDate = !empty($data['end_date']) ? trim($data['end_date']) : $startDate;
|
||||
$startTime = !empty($data['start_time']) ? trim($data['start_time']) : '09:00';
|
||||
$endTime = !empty($data['end_time']) ? trim($data['end_time']) : '17:00';
|
||||
$daysOfWeek = trim($data['days_of_week'] ?? '1,2,3,4,5');
|
||||
|
||||
$stmtSched = $db->prepare("
|
||||
INSERT INTO board_card_schedules (card_id, schedule_type, start_date, end_date, start_time, end_time, days_of_week)
|
||||
VALUES (?, 'DAILY_RANGE', ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
start_date = VALUES(start_date),
|
||||
end_date = VALUES(end_date),
|
||||
start_time = VALUES(start_time),
|
||||
end_time = VALUES(end_time),
|
||||
days_of_week = VALUES(days_of_week)
|
||||
");
|
||||
$stmtSched->execute([$cardId, $startDate, $endDate, $startTime, $endTime, $daysOfWeek]);
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'card_id' => $cardId,
|
||||
'board_id' => $boardId,
|
||||
'lane_id' => $laneId,
|
||||
'scheduled_on_timeline' => $scheduleOnTimeline,
|
||||
'message' => $scheduleOnTimeline
|
||||
? 'Item succesvol toegevoegd aan het Bord en ingepland op de Tijdlijn!'
|
||||
: 'Item succesvol toegevoegd aan het Bord!'
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user