Files
html/api/nps-collector.php

66 lines
2.4 KiB
PHP

<?php
/**
* WEVAL NPS Collector - sovereign 21avr2026
* Zero external tool (Typeform/etc). Local JSONL storage.
* GET /api/nps-collector.php?action=stats -> KPI ready
* POST /api/nps-collector.php?action=submit -> save response (score 0-10, comment)
*/
header('Content-Type: application/json');
$STORAGE = '/opt/weval-l99/data/nps-responses.jsonl';
@mkdir(dirname($STORAGE), 0755, true);
$action = $_GET['action'] ?? ($_POST['action'] ?? 'stats');
if ($action === 'submit' && $_SERVER['REQUEST_METHOD'] === 'POST') {
$score = intval($_POST['score'] ?? -1);
$comment = substr(trim($_POST['comment'] ?? ''), 0, 500);
$user = substr(trim($_POST['user'] ?? 'anonymous'), 0, 60);
if ($score < 0 || $score > 10) {
echo json_encode(['ok'=>false,'error'=>'invalid_score','expected'=>'0-10']);
exit;
}
$record = ['ts'=>date('c'),'score'=>$score,'comment'=>$comment,'user'=>$user,'ip'=>$_SERVER['REMOTE_ADDR']??''];
@file_put_contents($STORAGE, json_encode($record)."\n", FILE_APPEND | LOCK_EX);
echo json_encode(['ok'=>true,'recorded'=>$record]);
exit;
}
// stats = NPS score aggregation
$responses = [];
if (is_readable($STORAGE)) {
foreach (file($STORAGE) as $line) {
$r = @json_decode(trim($line), true);
if ($r && isset($r['score'])) $responses[] = $r;
}
}
$n = count($responses);
if ($n === 0) {
echo json_encode(['ok'=>true,'source'=>'sovereign_jsonl','ts'=>date('c'),'nps_score'=>0,'responses_total'=>0,'promoters'=>0,'passives'=>0,'detractors'=>0,'status'=>'wire_needed','drill'=>'No responses yet. Post to this endpoint with score+comment.','endpoint_submit'=>'/api/nps-collector.php?action=submit']);
exit;
}
$promoters = 0; $passives = 0; $detractors = 0;
foreach ($responses as $r) {
$s = $r['score'];
if ($s >= 9) $promoters++;
elseif ($s >= 7) $passives++;
else $detractors++;
}
$nps = round((($promoters - $detractors) / $n) * 100);
echo json_encode([
'ok'=>true,
'source'=>'sovereign_jsonl',
'ts'=>date('c'),
'nps_score'=>$nps,
'responses_total'=>$n,
'promoters'=>$promoters,
'passives'=>$passives,
'detractors'=>$detractors,
'status'=>$nps >= 50 ? 'ok' : ($nps >= 0 ? 'warn' : 'fail'),
'drill'=>"NPS = ((promoters - detractors) / total) * 100",
'recent_comments'=>array_slice(array_reverse(array_column($responses, 'comment')), 0, 5),
]);