129 lines
3.3 KiB
TypeScript
129 lines
3.3 KiB
TypeScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
// Define the vote option interface
|
|
export interface VoteOptionConfig {
|
|
id: string;
|
|
label: string;
|
|
}
|
|
|
|
// Define the survey response type
|
|
export type VoteOption = string; // Now a string that matches the option id
|
|
|
|
export interface SurveyResponse {
|
|
id: string; // Used only for internal tracking, not associated with the voter
|
|
vote: VoteOption;
|
|
comment?: string;
|
|
timestamp: string;
|
|
}
|
|
|
|
// Path to the data files
|
|
const DATA_FILE = path.join(process.cwd(), 'data', 'responses.json');
|
|
const TEXT_FILE = path.join(process.cwd(), 'data', 'editable_text.json');
|
|
|
|
// Ensure the data directory exists
|
|
function ensureDataDirectory() {
|
|
const dataDir = path.join(process.cwd(), 'data');
|
|
if (!fs.existsSync(dataDir)) {
|
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
// Get vote options from editable_text.json
|
|
export function getVoteOptions(): VoteOptionConfig[] {
|
|
ensureDataDirectory();
|
|
|
|
if (!fs.existsSync(TEXT_FILE)) {
|
|
// Default options if file doesn't exist
|
|
return [
|
|
{ id: 'yes', label: 'Ja, ich stimme zu' },
|
|
{ id: 'no', label: 'Nein, ich stimme nicht zu' },
|
|
{ id: 'abstain', label: 'Ich enthalte mich' }
|
|
];
|
|
}
|
|
|
|
try {
|
|
const data = fs.readFileSync(TEXT_FILE, 'utf-8');
|
|
const texts = JSON.parse(data);
|
|
|
|
const voteOptionsEntry = texts.find((text: { id: string }) => text.id === 'vote-options');
|
|
|
|
if (voteOptionsEntry && Array.isArray(voteOptionsEntry.content)) {
|
|
return voteOptionsEntry.content;
|
|
}
|
|
|
|
// Return default options if not found or invalid
|
|
return [
|
|
{ id: 'yes', label: 'Ja, ich stimme zu' },
|
|
{ id: 'no', label: 'Nein, ich stimme nicht zu' },
|
|
{ id: 'abstain', label: 'Ich enthalte mich' }
|
|
];
|
|
} catch (error) {
|
|
console.error('Error reading vote options:', error);
|
|
// Return default options on error
|
|
return [
|
|
{ id: 'yes', label: 'Ja, ich stimme zu' },
|
|
{ id: 'no', label: 'Nein, ich stimme nicht zu' },
|
|
{ id: 'abstain', label: 'Ich enthalte mich' }
|
|
];
|
|
}
|
|
}
|
|
|
|
// Get all survey responses
|
|
export function getAllResponses(): SurveyResponse[] {
|
|
ensureDataDirectory();
|
|
|
|
if (!fs.existsSync(DATA_FILE)) {
|
|
return [];
|
|
}
|
|
|
|
const data = fs.readFileSync(DATA_FILE, 'utf-8');
|
|
return JSON.parse(data);
|
|
}
|
|
|
|
// Save a new survey response
|
|
export function saveResponse(vote: VoteOption, comment?: string): SurveyResponse {
|
|
const responses = getAllResponses();
|
|
|
|
// Create a new response with a random ID (not associated with the voter)
|
|
const newResponse: SurveyResponse = {
|
|
id: uuidv4(), // Random ID only for internal tracking
|
|
vote,
|
|
comment,
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
|
|
responses.push(newResponse);
|
|
|
|
ensureDataDirectory();
|
|
fs.writeFileSync(DATA_FILE, JSON.stringify(responses, null, 2));
|
|
|
|
return newResponse;
|
|
}
|
|
|
|
// Get survey statistics
|
|
export function getSurveyStats() {
|
|
const responses = getAllResponses();
|
|
const voteOptions = getVoteOptions();
|
|
|
|
// Initialize stats object with total count
|
|
const stats: Record<string, number> = {
|
|
total: responses.length
|
|
};
|
|
|
|
// Initialize count for each vote option
|
|
voteOptions.forEach(option => {
|
|
stats[option.id] = 0;
|
|
});
|
|
|
|
// Count votes for each option
|
|
responses.forEach(response => {
|
|
if (stats[response.vote] !== undefined) {
|
|
stats[response.vote]++;
|
|
}
|
|
});
|
|
|
|
return stats;
|
|
}
|