Add 8 new tools: Hash Verifier, URL Tool, String Utils, Cron Explainer, IP Calc, Lorem Ipsum, CSV Viewer, Notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import { useState } from 'react';
|
||||
import axios from '../services/api';
|
||||
|
||||
const EXAMPLES = ['192.168.0.0/24', '10.0.0.0/8', '172.16.0.0/12'];
|
||||
|
||||
const INFO_FIELDS = [
|
||||
{ key: 'network', label: 'Netzwerkadresse' },
|
||||
{ key: 'broadcast', label: 'Broadcast-Adresse' },
|
||||
{ key: 'netmask', label: 'Subnetzmaske' },
|
||||
{ key: 'wildcard', label: 'Wildcard-Maske' },
|
||||
{ key: 'first_host', label: 'Erste nutzbare IP' },
|
||||
{ key: 'last_host', label: 'Letzte nutzbare IP' },
|
||||
{ key: 'total_hosts', label: 'Nutzbare Hosts' },
|
||||
{ key: 'prefix_length', label: 'Präfixlänge', format: (v) => `/${v}` },
|
||||
{ key: 'ip_class', label: 'IP-Klasse' },
|
||||
];
|
||||
|
||||
function IpCalcTool() {
|
||||
const [cidr, setCidr] = useState('');
|
||||
const [result, setResult] = useState(null);
|
||||
const [error, setError] = useState('');
|
||||
const [copiedKey, setCopiedKey] = useState('');
|
||||
|
||||
const calculate = async (val) => {
|
||||
const input = val !== undefined ? val : cidr;
|
||||
setError('');
|
||||
setResult(null);
|
||||
if (!input.trim()) {
|
||||
setError('Bitte CIDR eingeben.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await axios.post('/api/ip/calculate', { cidr: input });
|
||||
setResult(res.data);
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.message || 'Fehler bei der Berechnung');
|
||||
}
|
||||
};
|
||||
|
||||
const useExample = (val) => {
|
||||
setCidr(val);
|
||||
setError('');
|
||||
setResult(null);
|
||||
calculate(val);
|
||||
};
|
||||
|
||||
const copy = (key, text) => {
|
||||
navigator.clipboard.writeText(String(text));
|
||||
setCopiedKey(key);
|
||||
setTimeout(() => setCopiedKey(''), 1500);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<h2>IP / Subnetz Rechner</h2>
|
||||
<p style={{ color: 'var(--muted)', marginBottom: '16px', fontSize: '0.95rem' }}>
|
||||
CIDR-Netzwerke berechnen und analysieren.
|
||||
</p>
|
||||
|
||||
<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', marginBottom: '10px' }}>
|
||||
{EXAMPLES.map((ex) => (
|
||||
<button key={ex} className="ghost" onClick={() => useExample(ex)}
|
||||
style={{ fontFamily: 'monospace', fontSize: '0.85rem' }}>
|
||||
{ex}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', gap: '8px' }}>
|
||||
<input
|
||||
type="text"
|
||||
value={cidr}
|
||||
onChange={(e) => { setCidr(e.target.value); setResult(null); setError(''); }}
|
||||
placeholder="192.168.1.0/24"
|
||||
style={{ fontFamily: 'monospace', flex: 1 }}
|
||||
onKeyDown={(e) => e.key === 'Enter' && calculate()}
|
||||
/>
|
||||
<button onClick={() => calculate()} style={{ flexShrink: 0 }}>Berechnen</button>
|
||||
</div>
|
||||
|
||||
{error && <p className="error" style={{ marginTop: '12px' }}>{error}</p>}
|
||||
|
||||
{result && (
|
||||
<div style={{
|
||||
marginTop: '16px',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))',
|
||||
gap: '10px',
|
||||
}}>
|
||||
{INFO_FIELDS.map(({ key, label, format }) => {
|
||||
const value = format ? format(result[key]) : result[key];
|
||||
return (
|
||||
<div key={key} style={{
|
||||
padding: '12px 14px',
|
||||
background: 'var(--surface-2)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: '12px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '4px',
|
||||
}}>
|
||||
<span style={{ fontSize: '0.78rem', color: 'var(--muted)', fontWeight: 600 }}>{label}</span>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '8px' }}>
|
||||
<span style={{ fontFamily: 'monospace', color: 'var(--text)', fontSize: '0.95rem', wordBreak: 'break-all' }}>
|
||||
{String(value)}
|
||||
</span>
|
||||
<button
|
||||
className="ghost"
|
||||
onClick={() => copy(key, value)}
|
||||
style={{ flexShrink: 0, margin: 0, padding: '4px 10px', fontSize: '0.78rem' }}
|
||||
>
|
||||
{copiedKey === key ? '✓' : 'Kopieren'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default IpCalcTool;
|
||||
Reference in New Issue
Block a user