Compare commits

...

81 Commits

Author SHA1 Message Date
NiekRabelink e45f565365 Merge branch 'main' into dev (sync AI resiliency & fallbacks) 2026-09-23 10:50:26 +02:00
NiekRabelink 3dc09a11a7 fix(ai): prioritize flash models, prevent high-demand blocks, and add resilient brainstorm fallbacks 2026-09-23 10:49:52 +02:00
NiekRabelink f18f7d5794 Merge pull request 'Implement intelligent fallback for AI requests during high demand and rate limiting' (#98) from dev into main
Reviewed-on: #98
2026-09-23 08:24:46 +00:00
NiekRabelink 660f196c60 Merge pull request 'Enhance IP verification process: add email resend functionality and improve error logging' (#97) from dev into main
Reviewed-on: #97
2026-09-23 07:22:40 +00:00
NiekRabelink 8ddae4d883 Merge pull request 'Snelheid' (#96) from dev into main
Reviewed-on: #96
2026-09-16 11:54:05 +00:00
NiekRabelink 65f81d620c Merge pull request 'Change mail options' (#95) from dev into main
Reviewed-on: #95
2026-09-16 10:39:19 +00:00
NiekRabelink 20d8f93f77 Merge pull request 'Fix speed and error' (#94) from dev into main
Reviewed-on: #94
2026-09-16 10:23:33 +00:00
NiekRabelink 85850f47ad Merge pull request 'Dev' (#93) from dev into main
Reviewed-on: #93
2026-09-15 22:32:58 +00:00
NiekRabelink e9f54cbe72 Merge pull request 'Jira 27' (#92) from dev into main
Reviewed-on: #92
2026-09-15 20:39:10 +00:00
NiekRabelink 2d89e19114 Merge pull request 'Jira 26' (#91) from dev into main
Reviewed-on: #91
2026-09-15 20:32:23 +00:00
NiekRabelink 1ad383d27b Merge pull request 'Jira 25' (#90) from dev into main
Reviewed-on: #90
2026-09-15 20:12:27 +00:00
NiekRabelink a038d25489 Merge pull request 'Jira 24' (#89) from dev into main
Reviewed-on: #89
2026-09-15 20:05:01 +00:00
NiekRabelink 4a9ba4d76a Merge pull request 'Fix 23' (#88) from dev into main
Reviewed-on: #88
2026-09-15 19:16:08 +00:00
NiekRabelink e08b304c38 Merge pull request 'Jira22' (#87) from dev into main
Reviewed-on: #87
2026-09-15 16:40:43 +00:00
NiekRabelink 830fdf1330 Merge pull request 'Filter changes' (#86) from dev into main
Reviewed-on: #86
2026-09-15 14:26:22 +00:00
NiekRabelink d65463dab8 Merge pull request 'Jira repair' (#85) from dev into main
Reviewed-on: #85
2026-09-15 13:42:38 +00:00
NiekRabelink 843b75334e Merge pull request 'Dev' (#84) from dev into main
Reviewed-on: #84
2026-09-15 13:00:29 +00:00
NiekRabelink aa23ccdd73 Merge pull request 'Jira en admin aanpassingen' (#83) from dev into main
Reviewed-on: #83
2026-09-15 10:31:57 +00:00
NiekRabelink cb8246dba9 Merge pull request 'Jira aanpassingen' (#82) from dev into main
Reviewed-on: #82
2026-09-14 14:24:42 +00:00
NiekRabelink 5c4c53922b Merge pull request 'Header center' (#81) from dev into main
Reviewed-on: #81
2026-09-14 11:16:35 +00:00
NiekRabelink ee12d54350 Merge pull request 'Header redesign' (#80) from dev into main
Reviewed-on: #80
2026-09-14 10:15:33 +00:00
NiekRabelink 7e7f071f04 Merge pull request 'Dashboard' (#79) from dev into main
Reviewed-on: #79
2026-09-14 09:52:31 +00:00
NiekRabelink bf0d2f3bca Merge pull request 'Brainstorm huge refactor' (#78) from dev into main
Reviewed-on: #78
2026-09-14 09:11:25 +00:00
NiekRabelink 6a4981744f Merge pull request 'Fix brainstorm delete and plan button' (#77) from dev into main
Reviewed-on: #77
2026-09-14 08:29:13 +00:00
NiekRabelink 740b5343c4 Merge pull request 'Dev' (#76) from dev into main
Reviewed-on: #76
2026-09-14 08:08:27 +00:00
NiekRabelink 6987cab4f8 Merge pull request 'Verbetering postit' (#75) from dev into main
Reviewed-on: #75
2026-09-12 18:17:15 +00:00
NiekRabelink fd59cd69c1 Merge pull request 'Postit' (#74) from dev into main
Reviewed-on: #74
2026-09-12 18:13:19 +00:00
NiekRabelink 29874f184b Merge pull request 'Fix' (#73) from dev into main
Reviewed-on: #73
2026-09-12 16:13:16 +00:00
NiekRabelink 0bafe0afe9 Merge pull request 'Postits' (#72) from dev into main
Reviewed-on: #72
2026-09-12 15:24:09 +00:00
NiekRabelink 880c1bf9bb Merge pull request 'Dev' (#71) from dev into main
Reviewed-on: #71
2026-09-12 15:15:39 +00:00
NiekRabelink a0d99914e6 Merge pull request 'Dev nieuw' (#70) from dev into main
Reviewed-on: #70
2026-09-12 14:50:06 +00:00
NiekRabelink 1c3541e602 Merge pull request 'Ai aanpassingen en slepen in planner blokken' (#69) from dev into main
Reviewed-on: #69
2026-09-12 12:24:36 +00:00
NiekRabelink 845216e554 Merge pull request 'Brainstorm fix' (#68) from dev into main
Reviewed-on: #68
2026-09-12 11:45:39 +00:00
NiekRabelink 0ad186e95f Merge pull request 'Dev' (#67) from dev into main
Reviewed-on: #67
2026-09-12 11:24:10 +00:00
NiekRabelink 582ba9871f Merge pull request 'IT882' (#66) from dev into main
Reviewed-on: #66
2026-09-12 11:10:58 +00:00
NiekRabelink 9442dd7b38 Merge pull request 'AI fix' (#65) from dev into main
Reviewed-on: #65
2026-09-12 11:01:08 +00:00
NiekRabelink 046d344003 Merge pull request 'Ai fix' (#64) from dev into main
Reviewed-on: #64
2026-09-12 10:51:38 +00:00
NiekRabelink a1e9dd19ae Merge pull request 'Planner wijzigingen' (#63) from dev into main
Reviewed-on: #63
2026-09-12 10:50:24 +00:00
NiekRabelink d87a62e1f2 Merge pull request 'Error 500 fix' (#62) from dev into main
Reviewed-on: #62
2026-09-12 09:22:50 +00:00
NiekRabelink f389f67774 Merge pull request 'Fix' (#61) from dev into main
Reviewed-on: #61
2026-09-12 09:15:45 +00:00
NiekRabelink a1f2937504 Merge pull request 'Aanpassing planner' (#60) from dev into main
Reviewed-on: #60
2026-09-12 09:04:16 +00:00
NiekRabelink 51658e0aa9 Merge pull request 'Timzone' (#59) from dev into main
Reviewed-on: #59
2026-09-12 08:57:25 +00:00
NiekRabelink 8e62e73d46 Merge pull request 'Workdays' (#58) from dev into main
Reviewed-on: #58
2026-09-12 08:52:13 +00:00
NiekRabelink 41d3733f69 Merge pull request 'Last security check' (#57) from dev into main
Reviewed-on: #57
2026-09-12 08:26:59 +00:00
NiekRabelink 8095a63f31 Merge pull request 'Session guard refresh 1s' (#56) from dev into main
Reviewed-on: #56
2026-09-12 07:59:59 +00:00
NiekRabelink 30be1dfee9 Merge pull request 'Dev' (#55) from dev into main
Reviewed-on: #55
2026-09-11 20:20:49 +00:00
NiekRabelink ad06c67235 Merge pull request 'Dev' (#54) from dev into main
Reviewed-on: #54
2026-09-11 19:45:36 +00:00
NiekRabelink 7461231879 Merge pull request 'feat(planner): add functionality to find and plan tasks in the next available time slot, including date selection and UI updates' (#53) from dev into main
Reviewed-on: #53
2026-09-11 14:36:13 +00:00
NiekRabelink d870e643dc Merge pull request 'feat(jira): enhance Jira planning modal with customizable title, date input, and collapsible description' (#52) from dev into main
Reviewed-on: #52
2026-09-11 14:24:23 +00:00
NiekRabelink bc6fdd249e Merge pull request 'feat(avatar): implement avatar upload processing and validation, update user interface for avatar display' (#51) from dev into main
Reviewed-on: #51
2026-09-11 14:01:09 +00:00
NiekRabelink e3a4d862bd Merge pull request 'Dev' (#50) from dev into main
Reviewed-on: #50
2026-09-11 13:52:21 +00:00
NiekRabelink 2dc0afc7a0 Merge pull request 'feat(security): implement SOC 2 & ISO 27001 audit logging, password policy, and session timeout' (#49) from dev into main
Reviewed-on: #49
2026-09-11 13:43:22 +00:00
NiekRabelink e841d29b63 Merge branch 'dev' into main: fix widget layout persistence 2026-09-11 15:25:30 +02:00
NiekRabelink 6a9935e5cf fix(config): restore live config/.env and add DB connection safety net 2026-09-11 15:17:17 +02:00
NiekRabelink cc5d4a027f Merge pull request 'Dev' (#48) from dev into main
Reviewed-on: #48
2026-09-11 13:12:36 +00:00
NiekRabelink 0092cc17ef refactor(config): remove config/.env from git tracking, restore config/.env.example, and update .gitignore 2026-09-11 15:11:03 +02:00
NiekRabelink 29b8ce9211 Update config/.env 2026-09-11 13:03:51 +00:00
NiekRabelink cc439c8d0c Update config/.env 2026-09-11 13:00:56 +00:00
NiekRabelink 6060f39566 Merge pull request 'Implement CSRF protection for user invitation and management actions; add QR code generation script; secure internal includes directory with .htaccess' (#46) from dev into main
Reviewed-on: #46
2026-09-11 12:57:44 +00:00
NiekRabelink 4026efc816 Merge pull request 'Dev' (#45) from dev into main
Reviewed-on: #45
2026-09-11 11:27:27 +00:00
NiekRabelink 29adb48dd9 Merge pull request 'feat: Add story points support and AI daily briefing feature' (#44) from dev into main
Reviewed-on: #44
2026-09-10 20:38:37 +00:00
NiekRabelink bf944e063b Merge pull request 'Dev' (#43) from dev into main
Reviewed-on: #43
2026-09-10 14:51:56 +00:00
NiekRabelink b608e21ac2 Merge pull request 'Dev' (#42) from dev into main
Reviewed-on: #42
2026-09-10 14:16:04 +00:00
NiekRabelink 144721585c Merge pull request 'Dev' (#41) from dev into main
Reviewed-on: #41
2026-09-10 13:59:37 +00:00
NiekRabelink 2bc6c8c55d Merge pull request 'Enhance email rendering and Jira widget functionality' (#40) from dev into main
Reviewed-on: #40
2026-09-10 13:44:56 +00:00
NiekRabelink 26076f92f8 Merge pull request 'feat(cache): implement centralized caching layer for improved performance and reduced API calls' (#39) from dev into main
Reviewed-on: #39
2026-09-10 13:20:56 +00:00
NiekRabelink 0c6fa507b6 Merge pull request 'feat(microsoft-integration): update Microsoft 365 settings and admin consent handling for improved clarity and functionality' (#38) from dev into main
Reviewed-on: #38
2026-09-10 12:47:46 +00:00
NiekRabelink 35b8fa24f5 Merge pull request 'feat(microsoft-integration): enhance email permissions and consent flow for Outlook integration' (#37) from dev into main
Reviewed-on: #37
2026-09-10 12:42:52 +00:00
NiekRabelink df6dadee6f Merge pull request 'Implement code changes to enhance functionality and improve performance' (#36) from dev into main
Reviewed-on: #36
2026-09-10 12:30:21 +00:00
NiekRabelink 15caa5f341 Merge pull request 'feat(planner): add widget layout saving and scratchpad note functionality' (#35) from dev into main
Reviewed-on: #35
2026-09-10 12:17:54 +00:00
NiekRabelink c6e7a8d117 Merge pull request 'Dev' (#34) from dev into main
Reviewed-on: #34
2026-09-10 12:10:19 +00:00
NiekRabelink 2270e5875d Merge pull request 'Enhance Jira integration by adding fallback mechanisms and improving field handling in issue fetching' (#33) from dev into main
Reviewed-on: #33
2026-09-10 11:15:04 +00:00
NiekRabelink 64fbd8079d Merge pull request 'Dev' (#32) from dev into main
Reviewed-on: #32
2026-09-10 10:50:23 +00:00
NiekRabelink 9c4d1e9618 Merge pull request 'Add password reset functionality and SMTP mailer class' (#31) from dev into main
Reviewed-on: #31
2026-09-10 08:01:41 +00:00
NiekRabelink c65d4a2525 Merge pull request 'Refactor code structure for improved readability and maintainability' (#30) from dev into main
Reviewed-on: #30
2026-09-09 20:31:41 +00:00
NiekRabelink 08307f5fe7 Merge pull request 'Refactor board layout for improved full-width maximization and responsive design' (#29) from dev into main
Reviewed-on: #29
2026-09-09 20:07:05 +00:00
NiekRabelink 4163199d16 Merge pull request 'Allow board to always use full screen width and hide header on maximize' (#28) from dev into main
Reviewed-on: #28
2026-09-09 19:44:16 +00:00
NiekRabelink 302b6fb555 Merge pull request 'Update board layout: add small maximize icon directly above lanes and enable true full-width screen expansion' (#27) from dev into main
Reviewed-on: #27
2026-09-09 19:35:27 +00:00
NiekRabelink 4fbe30b4b6 Merge pull request 'Enhance board and planner UI; implement smooth width transitions, update icons, and improve layout responsiveness' (#26) from dev into main
Reviewed-on: #26
2026-09-09 19:21:48 +00:00
NiekRabelink c6b322cb49 Merge pull request 'Dev' (#25) from dev into main
Reviewed-on: #25
2026-09-09 19:03:34 +00:00
NiekRabelink bcf2323124 Merge pull request 'Enhance session management and user authentication flow; implement day session tokens, improve cookie handling, and streamline date handling in planner' (#24) from dev into main
Reviewed-on: #24
2026-09-09 17:19:18 +00:00
5 changed files with 108 additions and 30 deletions
+3 -4
View File
@@ -385,7 +385,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$activeTab = 'system';
try {
$aiEnabled = isset($_POST['ai_enabled']) ? 1 : 0;
$aiModel = trim((string)($_POST['ai_model'] ?? 'gemini-1.5-pro'));
$aiModel = trim((string)($_POST['ai_model'] ?? 'gemini-2.0-flash'));
$aiProvider = trim((string)($_POST['ai_provider'] ?? ''));
if (empty($aiProvider)) {
$aiProvider = str_contains($aiModel, 'gpt') ? 'openai' : 'gemini';
@@ -2126,10 +2126,9 @@ require_once __DIR__ . '/includes/header.php';
<label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">AI Provider & Model</label>
<select name="ai_model" id="admin_ai_model" class="w-full bg-slate-50 dark:bg-[#0c0f17] border border-slate-300 dark:border-slate-800 rounded-xl px-3 py-2 text-slate-900 dark:text-white text-xs focus:outline-none focus:ring-1 focus:ring-indigo-500">
<optgroup label="Google Gemini (Aanbevolen)">
<option value="gemini-3.6-flash" <?= ($aiSettings['ai_model'] === 'gemini-3.6-flash' || empty($aiSettings['ai_model']) || $aiSettings['ai_model'] === 'gemini') ? 'selected' : '' ?>>Google Gemini 3.6 Flash (Aanbevolen, Snel & Nieuwste)</option>
<option value="gemini-1.5-pro" <?= $aiSettings['ai_model'] === 'gemini-1.5-pro' ? 'selected' : '' ?>>Google Gemini 1.5 Pro (Slim & Uitgebreid)</option>
<option value="gemini-2.0-flash" <?= $aiSettings['ai_model'] === 'gemini-2.0-flash' ? 'selected' : '' ?>>Google Gemini 2.0 Flash</option>
<option value="gemini-2.0-flash" <?= ($aiSettings['ai_model'] === 'gemini-2.0-flash' || empty($aiSettings['ai_model']) || $aiSettings['ai_model'] === 'gemini' || $aiSettings['ai_model'] === 'gemini-3.6-flash') ? 'selected' : '' ?>>Google Gemini 2.0 Flash (Aanbevolen, Razendsnel)</option>
<option value="gemini-1.5-flash" <?= $aiSettings['ai_model'] === 'gemini-1.5-flash' ? 'selected' : '' ?>>Google Gemini 1.5 Flash</option>
<option value="gemini-1.5-pro" <?= $aiSettings['ai_model'] === 'gemini-1.5-pro' ? 'selected' : '' ?>>Google Gemini 1.5 Pro (Slim & Uitgebreid)</option>
</optgroup>
<optgroup label="OpenAI">
<option value="gpt-4o-mini" <?= $aiSettings['ai_model'] === 'gpt-4o-mini' ? 'selected' : '' ?>>OpenAI GPT-4o-mini</option>
+42 -6
View File
@@ -1598,10 +1598,38 @@ async function fetchAiBreakdown(content, attempt = 1, maxAttempts = 3) {
return;
}
document.getElementById('breakdownLoading').classList.add('hidden');
document.getElementById('breakdownError').classList.remove('hidden');
document.getElementById('breakdownErrorMsg').innerText = data.error || 'Geen taken gegenereerd door AI.';
return;
// Graceful Fallback: zorg dat het omzetten van het idee altijd vlekkeloos doorgaat
const cleanTitle = (content || '').split('\n')[0].substring(0, 60);
data = {
success: true,
items: [
{
title: 'Onderzoek & specificatie: ' + cleanTitle,
description: 'Randvoorwaarden en functionele specificaties vastleggen.',
priority: 'P1',
estimated_minutes: 45,
color: 'indigo',
category: 'Onderzoek'
},
{
title: 'Realisatie & uitwerking: ' + cleanTitle,
description: 'Implementatie en concrete uitvoering van het idee.',
priority: 'P2',
estimated_minutes: 90,
color: 'blue',
category: 'Frontend'
},
{
title: 'Kwaliteitscontrole & oplevering: ' + cleanTitle,
description: 'Testen, feedback verwerken en afronden.',
priority: 'P2',
estimated_minutes: 30,
color: 'emerald',
category: 'Testing'
}
],
summary: 'AI model had tijdelijke piekdruk; standaard deeltaken zijn direct klaargezet zodat je meteen kunt doorwerken.'
};
}
currentBreakdownItems = data.items.map((it, idx) => ({
@@ -1627,9 +1655,17 @@ async function fetchAiBreakdown(content, attempt = 1, maxAttempts = 3) {
setTimeout(() => fetchAiBreakdown(content, attempt + 1, maxAttempts), 2500);
return;
}
const cleanTitle = (content || '').split('\n')[0].substring(0, 60);
currentBreakdownItems = [
{ id: 1, selected: true, title: 'Onderzoek & specificatie: ' + cleanTitle, description: 'Randvoorwaarden en specificaties vastleggen.', priority: 'P1', estimated_minutes: 45, color: 'indigo', category: 'Onderzoek' },
{ id: 2, selected: true, title: 'Realisatie & uitwerking: ' + cleanTitle, description: 'Implementatie en concrete uitvoering van het idee.', priority: 'P2', estimated_minutes: 90, color: 'blue', category: 'Frontend' },
{ id: 3, selected: true, title: 'Kwaliteitscontrole & oplevering: ' + cleanTitle, description: 'Testen, feedback verwerken en afronden.', priority: 'P2', estimated_minutes: 30, color: 'emerald', category: 'Testing' }
];
document.getElementById('breakdownSummaryText').innerText = 'AI service was tijdelijk onbereikbaar; concept-deeltaken zijn direct klaargezet.';
renderBreakdownTasks();
document.getElementById('breakdownLoading').classList.add('hidden');
document.getElementById('breakdownError').classList.remove('hidden');
document.getElementById('breakdownErrorMsg').innerText = 'Netwerkfout bij communicatie met AI: ' + err.message;
document.getElementById('breakdownResult').classList.remove('hidden');
if (window.lucide) lucide.createIcons();
}
}
+58 -15
View File
@@ -160,30 +160,26 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
// Normaliseer modelnaam en stel geldige kandidatenlijst op
$candidateUrls = [];
// Helper om endpoints op te bouwen voor v1beta en v1
// Helper om endpoints op te bouwen (prioriteer v1beta voor moderne Gemini modellen)
$addCandidatesFor = function(string $m) use (&$candidateUrls) {
$m = preg_replace('#^models/#', '', trim($m));
if ($m === '') return;
$v1beta = "https://generativelanguage.googleapis.com/v1beta/models/{$m}:generateContent";
$v1 = "https://generativelanguage.googleapis.com/v1/models/{$m}:generateContent";
if (!in_array($v1beta, $candidateUrls, true)) {
$candidateUrls[] = $v1beta;
}
if (!in_array($v1, $candidateUrls, true)) {
$candidateUrls[] = $v1;
}
};
// Voeg het geconfigureerde model toe als eerste kandidaat (tenzij het een niet-bestaand/fictief model is)
// Voeg het geconfigureerde model toe als eerste kandidaat (mits niet fictief)
if (!empty($cleanModel) && !str_contains($cleanModel, '3.6-flash')) {
$addCandidatesFor($cleanModel);
}
// Voeg altijd de stabiele, snelle Google AI modellen toe als betrouwbare fallbacks/standaarden
// Voeg altijd de snelle, hoog-beschikbare Google AI modellen toe als betrouwbare fallbacks
$addCandidatesFor('gemini-2.0-flash');
$addCandidatesFor('gemini-1.5-flash');
$addCandidatesFor('gemini-1.5-pro');
$addCandidatesFor('gemini-2.5-flash');
$addCandidatesFor('gemini-1.5-pro');
$isHighDemandOrRateLimited = function(array $res, string $msg): bool {
$status = $res['status'] ?? 0;
@@ -274,7 +270,7 @@ function fociz_ai_chat_gemini(array $messages, array $options, array $aiSettings
break;
}
// Voor alle andere fouten (serverfout 500, timeout, etc.): probeer volgende kandidaat
// Voor alle andere fouten (serverfout 500, timeout, netwerkdip): probeer volgende kandidaat
continue;
}
@@ -656,9 +652,38 @@ function fociz_ai_breakdown_idea(string $ideaContent, string $sessionTitle = '',
if (empty($items)) {
error_log("[fociz_ai_breakdown_idea] Geen geldige items gevonden in response: " . substr((string)($aiRes['content'] ?? ''), 0, 500));
$shortTitle = mb_substr(explode("\n", trim($ideaContent))[0], 0, 60);
return [
'success' => false,
'error' => 'De AI gaf een antwoord maar kon de taken niet structureren. Probeer het nogmaals.',
'success' => true,
'summary' => "Dit idee is direct voorbereid in behapbare deeltaken.",
'items' => [
[
'title' => "Onderzoek & specificatie: {$shortTitle}",
'description' => "Randvoorwaarden en specificaties vastleggen voor: {$ideaContent}",
'estimated_minutes' => 45,
'priority' => 'P1',
'color' => 'indigo',
'category' => 'Onderzoek'
],
[
'title' => "Realisatie & uitwerking: {$shortTitle}",
'description' => "Implementatie en concrete uitvoering van het idee.",
'estimated_minutes' => 90,
'priority' => 'P2',
'color' => 'blue',
'category' => 'Frontend'
],
[
'title' => "Kwaliteitscontrole & oplevering: {$shortTitle}",
'description' => "Testen, feedback verwerken en afronden.",
'estimated_minutes' => 30,
'priority' => 'P2',
'color' => 'emerald',
'category' => 'Testing'
]
],
'model' => 'Smart Fallback',
'is_fallback' => true,
];
}
@@ -732,7 +757,13 @@ function fociz_ai_generate_ideas(string $sessionTitle, string $theme, int $count
], ['json_mode' => true, 'user_id' => $userId]);
if (!$aiRes['success'] || empty($aiRes['json']['ideas'])) {
return ['success' => false, 'error' => $aiRes['error'] ?? 'Kon geen ideeën genereren'];
$ideas = [
"Gebruikerservaring en flow optimaliseren voor {$sessionTitle}",
"Kernfunctionaliteit automatiseren om handmatig werk te reduceren",
"Koppelingen en integraties verkennen voor snellere afhandeling",
"Feedback- en validatielus inrichten met eindgebruikers"
];
return ['success' => true, 'ideas' => array_slice($ideas, 0, max(2, $count)), 'is_fallback' => true];
}
return ['success' => true, 'ideas' => $aiRes['json']['ideas']];
@@ -767,12 +798,24 @@ function fociz_ai_generate_session_board(string $sessionTitle, string $theme, st
$aiRes = fociz_ai_chat([
['role' => 'system', 'content' => $systemPrompt],
['role' => 'user', 'content' => "Genereer het complete brainstorm whiteboard op basis van de sessiebeschrijving."],
['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' => [
['content' => "Nieuwe visie en kernfunctionaliteit uitwerken voor {$sessionTitle}", 'category' => 'Ideeën'],
['content' => "Gebruikerservaring en self-service flow versterken", 'category' => 'Ideeën'],
['content' => "Onduidelijke randvoorwaarden of ontbrekende specificaties", 'category' => 'Knelpunten'],
['content' => "Handmatige stappen die vertraging en overbelasting veroorzaken", 'category' => 'Knelpunten'],
['content' => "Geautomatiseerd proces en herbruikbare templates inrichten", 'category' => 'Oplossingen'],
['content' => "Duidelijke acceptatiecriteria en testvalidatie vooraf", 'category' => 'Oplossingen'],
['content' => "Quick win: Korte validatiesessie organiseren met het team", 'category' => 'Quick Wins'],
['content' => "Quick win: Dashboard overzicht en checklist direct klaarzetten", 'category' => 'Quick Wins'],
],
'is_fallback' => true,
];
}
return ['success' => true, 'cards' => $aiRes['json']['cards']];
+2 -2
View File
@@ -191,9 +191,9 @@ function get_ai_settings(?int $userId = null): array {
$provider = 'gemini';
}
$model = !empty($personalModel) ? $personalModel : get_system_setting('ai_model', 'gemini-1.5-pro');
$model = !empty($personalModel) ? $personalModel : get_system_setting('ai_model', 'gemini-2.0-flash');
if (empty($model)) {
$model = (strpos((string)$provider, 'openai') !== false) ? 'gpt-4o-mini' : 'gemini-1.5-pro';
$model = (strpos((string)$provider, 'openai') !== false) ? 'gpt-4o-mini' : 'gemini-2.0-flash';
}
$apiKey = trim((string)$apiKey);
+3 -3
View File
@@ -136,7 +136,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
elseif ($action === 'save_personal_ai') {
$aiEnabled = isset($_POST['ai_enabled']) ? 1 : 0;
$aiProvider = trim($_POST['ai_provider'] ?? 'gemini');
$aiModel = trim($_POST['ai_model'] ?? 'gemini-1.5-pro');
$aiModel = trim($_POST['ai_model'] ?? 'gemini-2.0-flash');
$apiKeyIn = trim($_POST['ai_api_key'] ?? '');
// Haal eventueel bestaande integratie op
@@ -977,9 +977,9 @@ require_once __DIR__ . '/includes/header.php';
<label class="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">AI Provider & Model</label>
<select name="ai_model" id="profile_ai_model" class="w-full bg-white dark:bg-slate-900/60 border border-slate-200 dark:border-slate-800 rounded-xl px-3.5 py-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-indigo-500">
<optgroup label="Google Gemini (Aanbevolen)">
<option value="gemini-1.5-pro" <?= ($userAiSettings['ai_model'] === 'gemini-1.5-pro' || empty($userAiSettings['ai_model'])) ? 'selected' : '' ?>>Google Gemini 1.5 Pro (Aanbevolen)</option>
<option value="gemini-2.0-flash" <?= $userAiSettings['ai_model'] === 'gemini-2.0-flash' ? 'selected' : '' ?>>Google Gemini 2.0 Flash (Razendsnel)</option>
<option value="gemini-2.0-flash" <?= ($userAiSettings['ai_model'] === 'gemini-2.0-flash' || empty($userAiSettings['ai_model'])) ? 'selected' : '' ?>>Google Gemini 2.0 Flash (Aanbevolen, Razendsnel)</option>
<option value="gemini-1.5-flash" <?= $userAiSettings['ai_model'] === 'gemini-1.5-flash' ? 'selected' : '' ?>>Google Gemini 1.5 Flash</option>
<option value="gemini-1.5-pro" <?= $userAiSettings['ai_model'] === 'gemini-1.5-pro' ? 'selected' : '' ?>>Google Gemini 1.5 Pro</option>
</optgroup>
<optgroup label="OpenAI">
<option value="gpt-4o-mini" <?= $userAiSettings['ai_model'] === 'gpt-4o-mini' ? 'selected' : '' ?>>OpenAI GPT-4o-mini</option>