gitlink_help_center/api/feedback/store.js

84 lines
2.1 KiB
JavaScript

// api/feedback/store.js
const fs = require('fs');
const path = require('path');
const DATA_DIR = path.resolve(__dirname, '../../data');
const FEEDBACK_FILE = path.join(DATA_DIR, 'feedback.json');
const MAX_ENTRIES = 10000;
function ensureFile() {
if (!fs.existsSync(DATA_DIR)) {
fs.mkdirSync(DATA_DIR, { recursive: true });
}
if (!fs.existsSync(FEEDBACK_FILE)) {
fs.writeFileSync(FEEDBACK_FILE, '[]', 'utf-8');
}
}
function readAll() {
ensureFile();
try {
return JSON.parse(fs.readFileSync(FEEDBACK_FILE, 'utf-8'));
} catch {
return [];
}
}
function writeAll(entries) {
ensureFile();
fs.writeFileSync(FEEDBACK_FILE, JSON.stringify(entries, null, 2), 'utf-8');
}
function addFeedback({ docPath, vote, suggestion }) {
const entries = readAll();
const entry = {
id: Date.now().toString(36) + Math.random().toString(36).slice(2, 6),
docPath,
vote,
suggestion: suggestion || null,
timestamp: new Date().toISOString(),
};
entries.push(entry);
if (entries.length > MAX_ENTRIES) {
entries.splice(0, entries.length - MAX_ENTRIES);
}
writeAll(entries);
return entry;
}
function getStats() {
const entries = readAll();
const total = entries.length;
const yes = entries.filter(e => e.vote === 'yes').length;
const no = entries.filter(e => e.vote === 'no').length;
const withSuggestion = entries.filter(e => e.suggestion).length;
const byPath = {};
for (const e of entries) {
if (!byPath[e.docPath]) {
byPath[e.docPath] = { path: e.docPath, yes: 0, no: 0, suggestions: [] };
}
if (e.vote === 'yes') byPath[e.docPath].yes++;
else byPath[e.docPath].no++;
if (e.suggestion) {
byPath[e.docPath].suggestions.push({ text: e.suggestion, time: e.timestamp });
}
}
return {
total,
yes,
no,
helpfulRate: total > 0 ? Math.round((yes / total) * 100) : 0,
withSuggestion,
byPath: Object.values(byPath).sort((a, b) => (b.yes + b.no) - (a.yes + a.no)),
};
}
function getRecent(limit = 50) {
const entries = readAll();
return entries.slice(-limit).reverse();
}
module.exports = { addFeedback, getStats, getRecent };