78 lines
3.8 KiB
React
78 lines
3.8 KiB
React
import React, { useState } from 'react'
|
|
import { Link } from 'react-router-dom'
|
|
import { Search } from 'lucide-react'
|
|
import { useContent } from '../hooks/useContent'
|
|
import { formatDate } from '../utils/formatDate'
|
|
import { decodeHtml } from '../utils/decodeHtml'
|
|
import SEOHead from '../components/SEOHead'
|
|
|
|
export default function Kniepunkt() {
|
|
const [searchQuery, setSearchQuery] = useState('')
|
|
const { items } = useContent('kniepunkt', { pageSize: 1000 })
|
|
|
|
const filteredItems = items.filter(item => {
|
|
if (!searchQuery) return true
|
|
const query = searchQuery.toLowerCase()
|
|
return (
|
|
(item.title && item.title.toLowerCase().includes(query)) ||
|
|
(item.summary && item.summary.toLowerCase().includes(query)) ||
|
|
(item.body && item.body.toLowerCase().includes(query))
|
|
)
|
|
})
|
|
|
|
return (
|
|
<main style={{ paddingTop: '120px', minHeight: '100vh' }}>
|
|
<SEOHead title="Kniepunkt" description="Die Kniepunkt-Kolumne von Dr. André Knie über KI, Technologie und die Absurditäten des digitalen Wandels." url="/kniepunkt" />
|
|
<div className="app-container">
|
|
<div className="section-header">
|
|
<h1 className="section-title"><span className="text-gradient">Kniepunkt</span></h1>
|
|
<p className="section-subtitle">Wöchentliche KI-Kolumne. Nachrichten und Absurditäten rund um KI.</p>
|
|
</div>
|
|
|
|
<div style={{ maxWidth: '700px', margin: '0 auto 40px auto', position: 'relative' }}>
|
|
<div style={{ position: 'absolute', left: '16px', top: '50%', transform: 'translateY(-50%)', color: 'var(--text-secondary)' }}>
|
|
<Search size={20} />
|
|
</div>
|
|
<input
|
|
type="text"
|
|
placeholder="Kniepunkte durchsuchen..."
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
style={{
|
|
width: '100%',
|
|
padding: '16px 80px 16px 48px',
|
|
borderRadius: '12px',
|
|
border: '1px solid rgba(255,255,255,0.1)',
|
|
background: 'var(--glass-bg)',
|
|
color: 'var(--text-primary)',
|
|
fontSize: '1rem',
|
|
outline: 'none'
|
|
}}
|
|
/>
|
|
<div style={{ position: 'absolute', right: '16px', top: '50%', transform: 'translateY(-50%)', color: 'var(--text-secondary)', fontSize: '0.9rem' }}>
|
|
{filteredItems?.length || 0} / {items?.length || 0}
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '700px', margin: '0 auto' }}>
|
|
{filteredItems.map(issue => (
|
|
<Link to={`/kniepunkt/${issue.slug}`} key={issue.slug} className="glass-panel" style={{ padding: '0', display: 'flex', flexDirection: 'column', transition: 'transform 0.3s ease', overflow: 'hidden' }}>
|
|
{issue.image && (
|
|
<div style={{ width: '100%', height: '240px', overflow: 'hidden' }}>
|
|
<img src={issue.image.replace('.webp', '-thumb.webp')} alt={decodeHtml(issue.title)} loading="lazy" style={{ width: '100%', height: '100%', objectFit: 'cover', borderBottom: '1px solid rgba(255,255,255,0.1)' }} />
|
|
</div>
|
|
)}
|
|
<div style={{ padding: '24px' }}>
|
|
<h3 style={{ marginBottom: '8px' }}>{decodeHtml(issue.title)}</h3>
|
|
<p style={{ color: 'var(--text-secondary)', margin: 0, fontSize: '0.9rem' }}>{formatDate(issue.date)}</p>
|
|
{issue.summary && <p style={{ color: 'var(--text-secondary)', margin: '8px 0 0', fontSize: '0.95rem' }}>{decodeHtml(issue.summary)}</p>}
|
|
</div>
|
|
</Link>
|
|
))}
|
|
{filteredItems.length === 0 && <p style={{ textAlign: 'center', color: 'var(--text-secondary)' }}>Keine Kniepunkte für diese Suche gefunden.</p>}
|
|
</div>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|