ChatAskUserInput.tsx1 match
13}
1415export default function AskUserInput({
16question,
17inputType = "text",
ssscQuizadmin.http.ts7 matches
13
14// Database initialization - ensure table exists
15async function initDatabase() {
16await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
17id INTEGER PRIMARY KEY AUTOINCREMENT,
244});
245
246function generateDashboardHTML(stats: any[], submissions: any[], total: number, currentPage: number, totalPages: number): string {
247return `
248<!DOCTYPE html>
616
617<script>
618async function deleteSubmission(id) {
619if (!confirm('Are you sure you want to delete this submission? This action cannot be undone.')) {
620return;
670}
671
672function refreshData() {
673window.location.reload();
674}
675
676function showMessage(message, type) {
677// Create message element
678const messageDiv = document.createElement('div');
709
710// Add keyboard shortcuts
711document.addEventListener('keydown', function(e) {
712if (e.key === 'F5' || (e.ctrlKey && e.key === 'r')) {
713e.preventDefault();
721}
722
723function generateCSV(submissions: any[]): string {
724const headers = ['Email', 'Primary Archetype', 'Completion Time (ms)', 'Timestamp', 'Breakdown'];
725const rows = submissions.map(sub => [
5## ๐ Features
6
7### Core Functionality
8- **Email Collection**: Users must provide email to begin quiz
9- **Interactive Quiz**: 15 carefully crafted questions with smooth animations
52โ โโโ types.ts # TypeScript interfaces and types
53โ โโโ quizData.ts # Quiz questions and archetype information
54โ โโโ utils.ts # Shared utility functions
55โโโ main.tsx # Legacy entry point (redirects to index.http.ts)
56โโโ deno.json # Deno configuration
98
99#### Admin Dashboard (`admin.http.ts`)
100- Separate HTTP val for administrative functions
101- Real-time analytics and data visualization
102- Responsive table displaying all quiz submissions
103- Pagination for large datasets
104- CSV export functionality for data analysis
105- Mobile-optimized admin interface
106
181- **Email Validation**: Client and server-side validation
182- **Data Sanitization**: All inputs sanitized before database storage
183- **Privacy Focused**: No tracking beyond essential quiz functionality
184- **Secure Storage**: Encrypted database storage through Val Town
185
ssscQuizindex.http.ts9 matches
17
18// Initialize database with Val Town best practices
19async function initDatabase() {
20await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
21id INTEGER PRIMARY KEY AUTOINCREMENT,
161app.get("/api/test-email", async c => {
162try {
163console.log("Testing email functionality...");
164await email({
165from: config.emailConfig.from,
166replyTo: config.emailConfig.replyTo,
167subject: "Test Email from Social Archetype Quiz",
168text: "This is a test email to verify email functionality is working.",
169html: "<h1>Test Email</h1><p>This is a test email to verify email functionality is working.</p>",
170headers: {
171...config.emailConfig.headers,
323});
324
325// Enhanced email function following Val Town standards
326async function sendResultsEmail(userEmail: string, results: QuizResults, completionTime?: number) {
327const completionTimeText = completionTime
328? `Completion time: ${Math.round(completionTime / 1000)} seconds`
442
443// Enhanced admin notification following Val Town patterns
444async function sendAdminNotification(userEmail: string, results: QuizResults, completionTime?: number) {
445if (!config.adminEmail) return;
446
529}
530
531// Utility function to hash IP for privacy compliance
532async function hashIP(ip: string): Promise<string> {
533const encoder = new TextEncoder();
534const data = encoder.encode(ip + config.hashSalt);
1export default async function(req: Request) {
2const url = new URL(req.url);
3const api = url.searchParams.get('api') || 'jsonplaceholder';
2import { quizQuestions, archetypeInfo } from "./quizData.ts";
3
4export function calculateResults(answers: number[]): QuizResults {
5const archetypeCounts: Record<string, number> = {};
6
34}
35
36export function generateInsights(results: QuizResults, completionTime?: number): Record<string, any> {
37const insights: Record<string, any> = {};
38
67}
68
69export function validateEmail(email: string): boolean {
70const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
71return emailRegex.test(email);
72}
73
74export function shuffleArray<T>(array: T[]): T[] {
75const shuffled = [...array];
76for (let i = shuffled.length - 1; i > 0; i--) {
81}
82
83export function getRandomQuestions(count: number = quizQuestions.length): QuizQuestion[] {
84return shuffleArray(quizQuestions).slice(0, count);
85}
86
87export function formatTime(milliseconds: number): string {
88const seconds = Math.floor(milliseconds / 1000);
89const minutes = Math.floor(seconds / 60);
10import { calculateResults, generateInsights } from "../shared/utils.ts";
11
12function App() {
13const [quizState, setQuizState] = useState<QuizState>({
14phase: "email",
133}
134
135function client() {
136createRoot(document.getElementById("root")!).render(<App />);
137}
13}
14
15export default function QuizResultsComponent({
16results,
17email,
ssscQuizEmailScreen.tsx1 match
7}
8
9export default function EmailScreen({ onEmailSubmit }: EmailScreenProps) {
10const [email, setEmail] = useState("");
11const [error, setError] = useState("");
ssscQuizIntroScreen.tsx1 match
7}
8
9export default function IntroScreen({ email, onStart }: IntroScreenProps) {
10return (
11<div className="intro-screen fade-in">