From 51cd0af87ba8d8f9d4d1d956824fe2f3e5c60113 Mon Sep 17 00:00:00 2001 From: Lukas Davidovic Date: Wed, 6 Mar 2024 19:27:44 +0100 Subject: [PATCH] report form --- pages/api/reports.ts | 68 ++++++++++++++ pages/index.tsx | 49 +++++++++- pages/report.tsx | 212 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 324 insertions(+), 5 deletions(-) create mode 100644 pages/api/reports.ts create mode 100644 pages/report.tsx diff --git a/pages/api/reports.ts b/pages/api/reports.ts new file mode 100644 index 0000000..5f0aba2 --- /dev/null +++ b/pages/api/reports.ts @@ -0,0 +1,68 @@ +import type { NextApiRequest, NextApiResponse } from 'next' +import sqlite3 from 'sqlite3' +import path from 'path' + +function extractDomain(url: string): string { + try { + const urlObj = new URL(url) + return urlObj.hostname.replace('www.', '') + } catch { + return '' + } +} + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + if (req.method !== 'POST') { + return res.status(405).json({ error: 'Method not allowed' }) + } + + const { source_url, reporter_email, reporter_name, description, categories } = req.body + + if (!source_url || !description) { + return res.status(400).json({ error: 'URL and description are required' }) + } + + const domain = extractDomain(source_url) + if (!domain) { + return res.status(400).json({ error: 'Invalid URL format' }) + } + + const dbPath = path.join(process.cwd(), 'database', 'antihoax.db') + const db = new sqlite3.Database(dbPath) + + try { + await new Promise((resolve, reject) => { + db.run( + `INSERT INTO reports ( + source_url, source_domain, reporter_email, reporter_name, + category_suggestions, description, ip_address, user_agent + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + [ + source_url, + domain, + reporter_email || null, + reporter_name || null, + JSON.stringify(categories || []), + description, + req.headers['x-forwarded-for'] || req.connection.remoteAddress, + req.headers['user-agent'] + ], + function(err) { + if (err) reject(err) + else resolve() + } + ) + }) + + return res.status(200).json({ success: true, message: 'Report submitted successfully' }) + + } catch (error) { + console.error('Database error:', error) + return res.status(500).json({ error: 'Internal server error' }) + } finally { + db.close() + } +} \ No newline at end of file diff --git a/pages/index.tsx b/pages/index.tsx index 51a2908..d7c33f4 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,18 +1,57 @@ import type { NextPage } from 'next' import Head from 'next/head' +import Link from 'next/link' const Home: NextPage = () => { return (
- Infohliadka - + Infohliadka - Ochrana pred problematickými zdrojmi + -
-

Infohliadka

-

Vitajte na našej stránke!

+
+

Infohliadka

+

+ Platforma na ochranu pred hoaxmi, nenávistným prejavmi a dezinformáciami +

+ +
+
+

Nahlásiť obsah

+

+ Pomôžte nám identifikovať problematické stránky a obsah +

+ + Nahlásiť + +
+ +
+

Admin panel

+

+ Správa hlásení a moderovanie obsahu +

+ + Admin + +
+
) diff --git a/pages/report.tsx b/pages/report.tsx new file mode 100644 index 0000000..529df51 --- /dev/null +++ b/pages/report.tsx @@ -0,0 +1,212 @@ +import { useState } from 'react' +import type { NextPage } from 'next' +import Head from 'next/head' +import Link from 'next/link' + +const ReportPage: NextPage = () => { + const [formData, setFormData] = useState({ + source_url: '', + reporter_email: '', + reporter_name: '', + description: '', + categories: [] as string[] + }) + const [loading, setLoading] = useState(false) + const [success, setSuccess] = useState(false) + + const categories = [ + { id: 'hoax', name: 'Hoax' }, + { id: 'hate-speech', name: 'Hate Speech' }, + { id: 'violence', name: 'Violence' }, + { id: 'racism', name: 'Racism' }, + { id: 'conspiracy', name: 'Conspiracy' }, + { id: 'propaganda', name: 'Propaganda' } + ] + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + + try { + const response = await fetch('/api/reports', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(formData), + }) + + if (response.ok) { + setSuccess(true) + setFormData({ + source_url: '', + reporter_email: '', + reporter_name: '', + description: '', + categories: [] + }) + } + } catch (error) { + console.error('Failed to submit report:', error) + } finally { + setLoading(false) + } + } + + const handleCategoryChange = (categoryId: string, checked: boolean) => { + if (checked) { + setFormData(prev => ({ + ...prev, + categories: [...prev.categories, categoryId] + })) + } else { + setFormData(prev => ({ + ...prev, + categories: prev.categories.filter(id => id !== categoryId) + })) + } + } + + if (success) { + return ( +
+ + Hlásenie odoslané - Infohliadka + +
+

Ďakujeme!

+

Vaše hlásenie bolo úspešne odoslané a bude preverené našimi moderátormi.

+ ← Späť na hlavnú stránku +
+
+ ) + } + + return ( +
+ + Nahlásiť problematický obsah - Infohliadka + + +
+

Nahlásiť problematický obsah

+ +
+
+ + setFormData(prev => ({ ...prev, source_url: e.target.value }))} + style={{ + width: '100%', + padding: '8px', + border: '1px solid #d1d5db', + borderRadius: '4px' + }} + placeholder="https://example.com" + /> +
+ +
+ + setFormData(prev => ({ ...prev, reporter_email: e.target.value }))} + style={{ + width: '100%', + padding: '8px', + border: '1px solid #d1d5db', + borderRadius: '4px' + }} + placeholder="vas@email.com" + /> +
+ +
+ + setFormData(prev => ({ ...prev, reporter_name: e.target.value }))} + style={{ + width: '100%', + padding: '8px', + border: '1px solid #d1d5db', + borderRadius: '4px' + }} + placeholder="Vaše meno" + /> +
+ +
+ +
+ {categories.map(category => ( + + ))} +
+
+ +
+ +