Files
Tools/frontend/src/components/TimestampTool.jsx
T
Nirodan 7f9c5c874a Add 6 new tools: Hasher, Base64, JWT Decoder, Password Gen, Timestamp, Text Diff
- backend/tools/hasher.py: POST /api/hash/sha256 and /api/hash/bcrypt (bcrypt added to requirements)
- backend/tools/base64tool.py: POST /api/base64/encode and /api/base64/decode
- backend/tools/jwtdecoder.py: POST /api/jwt/decode (signature verification disabled)
- backend/tools/passwordgen.py: POST /api/password/generate with charset and length options
- backend/tools/timestamp.py: POST /api/timestamp/convert (unix<->date, ISO 8601 + German format)
- backend/tools/textdiff.py: POST /api/text/diff returning structured added/removed/unchanged lines
- All blueprints registered in app.py and tools/__init__.py
- React components with copy button, dark/light mode support via CSS variables
- ToolOverview rebuilt as card grid; App.jsx routes added for all tools

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 14:28:18 +02:00

102 lines
3.2 KiB
React

import { useState, useEffect } from 'react';
import axios from '../services/api';
const resultBox = {
marginTop: '12px',
padding: '12px 14px',
background: 'var(--surface-2)',
border: '1px solid var(--border)',
borderRadius: '12px',
display: 'flex',
alignItems: 'center',
gap: '10px',
justifyContent: 'space-between',
};
function TimestampTool() {
const [value, setValue] = useState('');
const [direction, setDirection] = useState('unix_to_date');
const [result, setResult] = useState(null);
const [copied, setCopied] = useState(false);
const [error, setError] = useState('');
const [now, setNow] = useState(Math.floor(Date.now() / 1000));
useEffect(() => {
const interval = setInterval(() => setNow(Math.floor(Date.now() / 1000)), 1000);
return () => clearInterval(interval);
}, []);
const convert = async () => {
setError('');
setResult(null);
try {
const res = await axios.post('/api/timestamp/convert', { value, direction });
setResult(res.data);
} catch (err) {
setError(err.response?.data?.message || 'Ungültiger Wert');
}
};
const resultText = result
? direction === 'unix_to_date' ? result.utc : String(result.unix)
: '';
const copy = () => {
navigator.clipboard.writeText(resultText);
setCopied(true);
setTimeout(() => setCopied(false), 1500);
};
return (
<div className="main-content">
<h2>Timestamp Converter</h2>
<div style={{ marginBottom: '12px', padding: '10px 14px', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: '12px' }}>
<span className="muted" style={{ fontSize: '0.875rem' }}>Aktueller Unix Timestamp: </span>
<span style={{ fontFamily: 'monospace', color: 'var(--accent)', fontWeight: 700 }}>{now}</span>
</div>
<div style={{ display: 'flex', gap: '8px', marginBottom: '12px' }}>
{[
{ key: 'unix_to_date', label: 'Unix → Datum' },
{ key: 'date_to_unix', label: 'Datum → Unix' },
].map(({ key, label }) => (
<button
key={key}
className={direction === key ? '' : 'ghost'}
onClick={() => { setDirection(key); setResult(null); setError(''); }}
style={{ margin: 0 }}
>
{label}
</button>
))}
</div>
<input
type="text"
value={value}
onChange={(e) => { setValue(e.target.value); setResult(null); setError(''); }}
placeholder={direction === 'unix_to_date' ? 'z.B. 1700000000' : 'z.B. 2024-01-15 oder 15.01.2024'}
/>
<button onClick={convert}>Konvertieren</button>
{error && <p className="error">{error}</p>}
{result && (
<div style={resultBox}>
<div>
{direction === 'unix_to_date' ? (
<span style={{ fontFamily: 'monospace', color: 'var(--text)' }}>{result.utc}</span>
) : (
<span style={{ fontFamily: 'monospace', color: 'var(--text)' }}>{result.unix}</span>
)}
</div>
<button className="ghost" onClick={copy} style={{ flexShrink: 0, margin: 0 }}>
{copied ? 'Kopiert!' : 'Kopieren'}
</button>
</div>
)}
</div>
);
}
export default TimestampTool;