feat: Curator-Hilfe-System implementiert
- Hilfe-Seite /curator/help mit vollständiger Dokumentation (de/en) - HelpTooltip-Komponente mit Hover- und Click-Modi - Tooltips bei allen wichtigen Dashboard-Bereichen: * Dashboard-Übersicht * Upload-Bereich & Genre-Zuweisung * Track-Liste (Suche, Filter, Batch-Edit) * Kommentar-Verwaltung - Prominenter Hilfe-Button im Header - Umfassende Übersetzungen für alle Hilfe-Texte - Fix: TypeScript-Fehler in batch route behoben - Fix: Doppelter Browser-Tooltip entfernt (nur noch custom Tooltip)
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslations, useLocale } from 'next-intl';
|
||||
import { Link } from '@/lib/navigation';
|
||||
import HelpTooltip from '@/components/HelpTooltip';
|
||||
|
||||
interface Genre {
|
||||
id: number;
|
||||
@@ -83,6 +85,8 @@ function getCuratorUploadHeaders() {
|
||||
export default function CuratorPageClient() {
|
||||
const t = useTranslations('Curator');
|
||||
const tNav = useTranslations('Navigation');
|
||||
const tHelp = useTranslations('CuratorHelp');
|
||||
const locale = useLocale();
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
@@ -787,7 +791,14 @@ export default function CuratorPageClient() {
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<h1 style={{ fontSize: '1.75rem', marginBottom: '0.25rem' }}>Kuratoren-Dashboard</h1>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
<h1 style={{ fontSize: '1.75rem', marginBottom: '0.25rem' }}>Kuratoren-Dashboard</h1>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipDashboardShort')}
|
||||
longText={tHelp('tooltipDashboardLong')}
|
||||
position="bottom"
|
||||
/>
|
||||
</div>
|
||||
{curatorInfo && (
|
||||
<p style={{ color: '#4b5563', fontSize: '0.9rem' }}>
|
||||
{t('loggedInAs', { username: curatorInfo.username })}
|
||||
@@ -795,20 +806,38 @@ export default function CuratorPageClient() {
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleLogout}
|
||||
style={{
|
||||
padding: '0.5rem 1rem',
|
||||
background: '#6b7280',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '0.375rem',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
{t('logout')}
|
||||
</button>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
<Link
|
||||
href={`/${locale}/curator/help`}
|
||||
style={{
|
||||
padding: '0.5rem 1rem',
|
||||
background: '#3b82f6',
|
||||
color: 'white',
|
||||
textDecoration: 'none',
|
||||
borderRadius: '0.375rem',
|
||||
fontSize: '0.9rem',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.25rem',
|
||||
}}
|
||||
>
|
||||
❓ {tHelp('helpButton')}
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleLogout}
|
||||
style={{
|
||||
padding: '0.5rem 1rem',
|
||||
background: '#6b7280',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '0.375rem',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
{t('logout')}
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{loading && <p>{t('loadingData')}</p>}
|
||||
@@ -825,9 +854,16 @@ export default function CuratorPageClient() {
|
||||
<section style={{ marginBottom: '2rem' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.75rem' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'baseline', gap: '0.75rem' }}>
|
||||
<h2 style={{ fontSize: '1.25rem', marginBottom: 0 }}>
|
||||
{t('commentsTitle')} ({comments.length})
|
||||
</h2>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
<h2 style={{ fontSize: '1.25rem', marginBottom: 0 }}>
|
||||
{t('commentsTitle')} ({comments.length})
|
||||
</h2>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipCommentsShort')}
|
||||
longText={tHelp('tooltipCommentsLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
{hasUnread && (
|
||||
<span style={{
|
||||
padding: '0.25rem 0.75rem',
|
||||
@@ -978,7 +1014,14 @@ export default function CuratorPageClient() {
|
||||
})()}
|
||||
|
||||
<section style={{ marginBottom: '2rem' }}>
|
||||
<h2 style={{ fontSize: '1.25rem', marginBottom: '0.75rem' }}>{t('uploadSectionTitle')}</h2>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.75rem' }}>
|
||||
<h2 style={{ fontSize: '1.25rem', margin: 0 }}>{t('uploadSectionTitle')}</h2>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipUploadShort')}
|
||||
longText={tHelp('tooltipUploadLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
<p style={{ marginBottom: '0.75rem', color: '#4b5563', fontSize: '0.9rem' }}>
|
||||
{t('uploadSectionDescription')}
|
||||
</p>
|
||||
@@ -1078,7 +1121,14 @@ export default function CuratorPageClient() {
|
||||
)}
|
||||
|
||||
<div>
|
||||
<div style={{ fontWeight: 500, marginBottom: '0.25rem' }}>{t('assignGenresLabel')}</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.25rem' }}>
|
||||
<div style={{ fontWeight: 500 }}>{t('assignGenresLabel')}</div>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipGenreAssignmentShort')}
|
||||
longText={tHelp('tooltipGenreAssignmentLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.25rem' }}>
|
||||
{genres
|
||||
.filter(g => curatorInfo?.genreIds?.includes(g.id))
|
||||
@@ -1154,70 +1204,91 @@ export default function CuratorPageClient() {
|
||||
</section>
|
||||
|
||||
<section style={{ marginBottom: '2rem' }}>
|
||||
<h2 style={{ fontSize: '1.25rem', marginBottom: '0.75rem' }}>
|
||||
{t('tracklistTitle', { count: filteredSongs.length })}
|
||||
</h2>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.75rem' }}>
|
||||
<h2 style={{ fontSize: '1.25rem', margin: 0 }}>
|
||||
{t('tracklistTitle', { count: filteredSongs.length })}
|
||||
</h2>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipTracklistShort')}
|
||||
longText={tHelp('tooltipTracklistLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
<p style={{ marginBottom: '0.75rem', color: '#4b5563', fontSize: '0.9rem' }}>
|
||||
{t('tracklistDescription')}
|
||||
</p>
|
||||
|
||||
{/* Suche & Filter */}
|
||||
<div style={{ marginBottom: '0.75rem', display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={t('searchPlaceholder')}
|
||||
value={searchQuery}
|
||||
onChange={e => {
|
||||
setSearchQuery(e.target.value);
|
||||
setCurrentPage(1);
|
||||
}}
|
||||
style={{
|
||||
flex: '1',
|
||||
minWidth: '200px',
|
||||
padding: '0.4rem 0.6rem',
|
||||
borderRadius: '0.25rem',
|
||||
border: '1px solid #d1d5db',
|
||||
}}
|
||||
/>
|
||||
<select
|
||||
value={selectedFilter}
|
||||
onChange={e => {
|
||||
setSelectedFilter(e.target.value);
|
||||
setCurrentPage(1);
|
||||
}}
|
||||
style={{
|
||||
minWidth: '180px',
|
||||
padding: '0.4rem 0.6rem',
|
||||
borderRadius: '0.25rem',
|
||||
border: '1px solid #d1d5db',
|
||||
}}
|
||||
>
|
||||
<option value="">{t('filterAll')}</option>
|
||||
<option value="no-global">{t('filterNoGlobal')}</option>
|
||||
<optgroup label="Genres">
|
||||
{genres
|
||||
.filter(g => curatorInfo?.genreIds?.includes(g.id))
|
||||
.map(genre => (
|
||||
<option key={genre.id} value={`genre:${genre.id}`}>
|
||||
{typeof genre.name === 'string'
|
||||
? genre.name
|
||||
: genre.name?.de ?? genre.name?.en}
|
||||
</option>
|
||||
))}
|
||||
</optgroup>
|
||||
<optgroup label="Specials">
|
||||
{specials
|
||||
.filter(s => curatorInfo?.specialIds?.includes(s.id))
|
||||
.map(special => (
|
||||
<option key={special.id} value={`special:${special.id}`}>
|
||||
★{' '}
|
||||
{typeof special.name === 'string'
|
||||
? special.name
|
||||
: special.name?.de ?? special.name?.en}
|
||||
</option>
|
||||
))}
|
||||
</optgroup>
|
||||
</select>
|
||||
<div style={{ marginBottom: '0.75rem', display: 'flex', gap: '0.5rem', flexWrap: 'wrap', alignItems: 'center' }}>
|
||||
<div style={{ flex: '1', minWidth: '200px', display: 'flex', alignItems: 'center', gap: '0.25rem' }}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={t('searchPlaceholder')}
|
||||
value={searchQuery}
|
||||
onChange={e => {
|
||||
setSearchQuery(e.target.value);
|
||||
setCurrentPage(1);
|
||||
}}
|
||||
style={{
|
||||
flex: '1',
|
||||
minWidth: '200px',
|
||||
padding: '0.4rem 0.6rem',
|
||||
borderRadius: '0.25rem',
|
||||
border: '1px solid #d1d5db',
|
||||
}}
|
||||
/>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipSearchShort')}
|
||||
longText={tHelp('tooltipSearchLong')}
|
||||
position="top"
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.25rem' }}>
|
||||
<select
|
||||
value={selectedFilter}
|
||||
onChange={e => {
|
||||
setSelectedFilter(e.target.value);
|
||||
setCurrentPage(1);
|
||||
}}
|
||||
style={{
|
||||
minWidth: '180px',
|
||||
padding: '0.4rem 0.6rem',
|
||||
borderRadius: '0.25rem',
|
||||
border: '1px solid #d1d5db',
|
||||
}}
|
||||
>
|
||||
<option value="">{t('filterAll')}</option>
|
||||
<option value="no-global">{t('filterNoGlobal')}</option>
|
||||
<optgroup label="Genres">
|
||||
{genres
|
||||
.filter(g => curatorInfo?.genreIds?.includes(g.id))
|
||||
.map(genre => (
|
||||
<option key={genre.id} value={`genre:${genre.id}`}>
|
||||
{typeof genre.name === 'string'
|
||||
? genre.name
|
||||
: genre.name?.de ?? genre.name?.en}
|
||||
</option>
|
||||
))}
|
||||
</optgroup>
|
||||
<optgroup label="Specials">
|
||||
{specials
|
||||
.filter(s => curatorInfo?.specialIds?.includes(s.id))
|
||||
.map(special => (
|
||||
<option key={special.id} value={`special:${special.id}`}>
|
||||
★{' '}
|
||||
{typeof special.name === 'string'
|
||||
? special.name
|
||||
: special.name?.de ?? special.name?.en}
|
||||
</option>
|
||||
))}
|
||||
</optgroup>
|
||||
</select>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipFilterShort')}
|
||||
longText={tHelp('tooltipFilterLong')}
|
||||
position="top"
|
||||
/>
|
||||
</div>
|
||||
{(searchQuery || selectedFilter) && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -1256,9 +1327,16 @@ export default function CuratorPageClient() {
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.75rem' }}>
|
||||
<strong style={{ fontSize: '1rem' }}>
|
||||
{t('batchEditTitle') || `Batch Edit: ${selectedSongIds.size} ${selectedSongIds.size === 1 ? 'song' : 'songs'} selected`}
|
||||
</strong>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
<strong style={{ fontSize: '1rem' }}>
|
||||
{t('batchEditTitle') || `Batch Edit: ${selectedSongIds.size} ${selectedSongIds.size === 1 ? 'song' : 'songs'} selected`}
|
||||
</strong>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipBatchEditShort')}
|
||||
longText={tHelp('tooltipBatchEditLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={clearSelection}
|
||||
@@ -1278,9 +1356,16 @@ export default function CuratorPageClient() {
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
|
||||
{/* Genre Toggle */}
|
||||
<div>
|
||||
<label style={{ display: 'block', fontWeight: 500, marginBottom: '0.25rem', fontSize: '0.9rem' }}>
|
||||
{t('batchToggleGenres') || 'Toggle Genres'}
|
||||
</label>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.25rem' }}>
|
||||
<label style={{ display: 'block', fontWeight: 500, fontSize: '0.9rem', margin: 0 }}>
|
||||
{t('batchToggleGenres') || 'Toggle Genres'}
|
||||
</label>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipBatchGenreToggleShort')}
|
||||
longText={tHelp('tooltipBatchGenreToggleLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.25rem' }}>
|
||||
{genres
|
||||
.filter(g => curatorInfo?.genreIds?.includes(g.id))
|
||||
@@ -1319,9 +1404,16 @@ export default function CuratorPageClient() {
|
||||
|
||||
{/* Special Toggle */}
|
||||
<div>
|
||||
<label style={{ display: 'block', fontWeight: 500, marginBottom: '0.25rem', fontSize: '0.9rem' }}>
|
||||
{t('batchToggleSpecials') || 'Toggle Specials'}
|
||||
</label>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.25rem' }}>
|
||||
<label style={{ display: 'block', fontWeight: 500, fontSize: '0.9rem', margin: 0 }}>
|
||||
{t('batchToggleSpecials') || 'Toggle Specials'}
|
||||
</label>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipBatchSpecialToggleShort')}
|
||||
longText={tHelp('tooltipBatchSpecialToggleLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.25rem' }}>
|
||||
{specials
|
||||
.filter(s => curatorInfo?.specialIds?.includes(s.id))
|
||||
@@ -1361,9 +1453,16 @@ export default function CuratorPageClient() {
|
||||
|
||||
{/* Artist Change */}
|
||||
<div>
|
||||
<label style={{ display: 'block', fontWeight: 500, marginBottom: '0.25rem', fontSize: '0.9rem' }}>
|
||||
{t('batchChangeArtist') || 'Change Artist'}
|
||||
</label>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.25rem' }}>
|
||||
<label style={{ display: 'block', fontWeight: 500, fontSize: '0.9rem', margin: 0 }}>
|
||||
{t('batchChangeArtist') || 'Change Artist'}
|
||||
</label>
|
||||
<HelpTooltip
|
||||
shortText={tHelp('tooltipBatchArtistShort')}
|
||||
longText={tHelp('tooltipBatchArtistLong')}
|
||||
position="right"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
value={batchArtist}
|
||||
|
||||
149
app/curator/help/CuratorHelpClient.tsx
Normal file
149
app/curator/help/CuratorHelpClient.tsx
Normal file
@@ -0,0 +1,149 @@
|
||||
'use client';
|
||||
|
||||
import { useTranslations, useLocale } from 'next-intl';
|
||||
import { Link } from '@/lib/navigation';
|
||||
|
||||
export default function CuratorHelpClient() {
|
||||
const t = useTranslations('CuratorHelp');
|
||||
const locale = useLocale();
|
||||
|
||||
return (
|
||||
<main style={{ maxWidth: '960px', margin: '2rem auto', padding: '1rem' }}>
|
||||
<header style={{ marginBottom: '2rem' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<h1 style={{ fontSize: '1.75rem', marginBottom: '0.25rem' }}>{t('title')}</h1>
|
||||
<Link
|
||||
href={`/${locale}/curator`}
|
||||
style={{
|
||||
padding: '0.5rem 1rem',
|
||||
background: '#6b7280',
|
||||
color: 'white',
|
||||
textDecoration: 'none',
|
||||
borderRadius: '0.375rem',
|
||||
fontSize: '0.9rem',
|
||||
}}
|
||||
>
|
||||
{t('backToDashboard')}
|
||||
</Link>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||
{/* Einführung */}
|
||||
<section>
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '1rem', borderBottom: '2px solid #e5e7eb', paddingBottom: '0.5rem' }}>
|
||||
{t('introductionTitle')}
|
||||
</h2>
|
||||
<div style={{ fontSize: '0.95rem', lineHeight: '1.7' }}>
|
||||
<p style={{ marginBottom: '1rem' }}>{t('introductionText')}</p>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1.5rem', marginBottom: '0.75rem' }}>{t('permissionsTitle')}</h3>
|
||||
<ul style={{ marginLeft: '1.5rem', marginBottom: '1rem' }}>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('permission1')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('permission2')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('permission3')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('permission4')}</li>
|
||||
</ul>
|
||||
<p style={{ marginTop: '1rem', padding: '0.75rem', background: '#fef3c7', borderRadius: '0.375rem', border: '1px solid #fbbf24' }}>
|
||||
<strong>{t('note')}:</strong> {t('permissionNote')}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Song-Upload */}
|
||||
<section>
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '1rem', borderBottom: '2px solid #e5e7eb', paddingBottom: '0.5rem' }}>
|
||||
{t('uploadTitle')}
|
||||
</h2>
|
||||
<div style={{ fontSize: '0.95rem', lineHeight: '1.7' }}>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1rem', marginBottom: '0.75rem' }}>{t('uploadStepsTitle')}</h3>
|
||||
<ol style={{ marginLeft: '1.5rem', marginBottom: '1rem' }}>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('uploadStep1')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('uploadStep2')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('uploadStep3')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('uploadStep4')}</li>
|
||||
</ol>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1.5rem', marginBottom: '0.75rem' }}>{t('uploadBestPracticesTitle')}</h3>
|
||||
<ul style={{ marginLeft: '1.5rem', marginBottom: '1rem' }}>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('uploadBestPractice1')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('uploadBestPractice2')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('uploadBestPractice3')}</li>
|
||||
</ul>
|
||||
<p style={{ marginTop: '1rem', padding: '0.75rem', background: '#dbeafe', borderRadius: '0.375rem', border: '1px solid #3b82f6' }}>
|
||||
<strong>{t('tip')}:</strong> {t('uploadTip')}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Song-Bearbeitung */}
|
||||
<section>
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '1rem', borderBottom: '2px solid #e5e7eb', paddingBottom: '0.5rem' }}>
|
||||
{t('editingTitle')}
|
||||
</h2>
|
||||
<div style={{ fontSize: '0.95rem', lineHeight: '1.7' }}>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1rem', marginBottom: '0.75rem' }}>{t('singleEditTitle')}</h3>
|
||||
<p style={{ marginBottom: '1rem' }}>{t('singleEditText')}</p>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1.5rem', marginBottom: '0.75rem' }}>{t('batchEditTitle')}</h3>
|
||||
<p style={{ marginBottom: '1rem' }}>{t('batchEditText')}</p>
|
||||
<ul style={{ marginLeft: '1.5rem', marginBottom: '1rem' }}>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('batchEditFeature1')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('batchEditFeature2')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('batchEditFeature3')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}>{t('batchEditFeature4')}</li>
|
||||
</ul>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1.5rem', marginBottom: '0.75rem' }}>{t('genreSpecialAssignmentTitle')}</h3>
|
||||
<p style={{ marginBottom: '1rem' }}>{t('genreSpecialAssignmentText')}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Kommentar-Verwaltung */}
|
||||
<section>
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '1rem', borderBottom: '2px solid #e5e7eb', paddingBottom: '0.5rem' }}>
|
||||
{t('commentsTitle')}
|
||||
</h2>
|
||||
<div style={{ fontSize: '0.95rem', lineHeight: '1.7' }}>
|
||||
<p style={{ marginBottom: '1rem' }}>{t('commentsText')}</p>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1rem', marginBottom: '0.75rem' }}>{t('commentsActionsTitle')}</h3>
|
||||
<ul style={{ marginLeft: '1.5rem', marginBottom: '1rem' }}>
|
||||
<li style={{ marginBottom: '0.5rem' }}><strong>{t('markAsRead')}:</strong> {t('markAsReadText')}</li>
|
||||
<li style={{ marginBottom: '0.5rem' }}><strong>{t('archive')}:</strong> {t('archiveText')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Best Practices */}
|
||||
<section>
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '1rem', borderBottom: '2px solid #e5e7eb', paddingBottom: '0.5rem' }}>
|
||||
{t('bestPracticesTitle')}
|
||||
</h2>
|
||||
<div style={{ fontSize: '0.95rem', lineHeight: '1.7' }}>
|
||||
<ul style={{ marginLeft: '1.5rem', marginBottom: '1rem' }}>
|
||||
<li style={{ marginBottom: '0.75rem' }}>{t('bestPractice1')}</li>
|
||||
<li style={{ marginBottom: '0.75rem' }}>{t('bestPractice2')}</li>
|
||||
<li style={{ marginBottom: '0.75rem' }}>{t('bestPractice3')}</li>
|
||||
<li style={{ marginBottom: '0.75rem' }}>{t('bestPractice4')}</li>
|
||||
<li style={{ marginBottom: '0.75rem' }}>{t('bestPractice5')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Troubleshooting */}
|
||||
<section>
|
||||
<h2 style={{ fontSize: '1.5rem', marginBottom: '1rem', borderBottom: '2px solid #e5e7eb', paddingBottom: '0.5rem' }}>
|
||||
{t('troubleshootingTitle')}
|
||||
</h2>
|
||||
<div style={{ fontSize: '0.95rem', lineHeight: '1.7' }}>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1rem', marginBottom: '0.75rem' }}>{t('troubleshootingQ1')}</h3>
|
||||
<p style={{ marginBottom: '1rem', marginLeft: '1rem' }}>{t('troubleshootingA1')}</p>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1rem', marginBottom: '0.75rem' }}>{t('troubleshootingQ2')}</h3>
|
||||
<p style={{ marginBottom: '1rem', marginLeft: '1rem' }}>{t('troubleshootingA2')}</p>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1rem', marginBottom: '0.75rem' }}>{t('troubleshootingQ3')}</h3>
|
||||
<p style={{ marginBottom: '1rem', marginLeft: '1rem' }}>{t('troubleshootingA3')}</p>
|
||||
<h3 style={{ fontSize: '1.1rem', marginTop: '1rem', marginBottom: '0.75rem' }}>{t('troubleshootingQ4')}</h3>
|
||||
<p style={{ marginBottom: '1rem', marginLeft: '1rem' }}>{t('troubleshootingA4')}</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
8
app/curator/help/page.tsx
Normal file
8
app/curator/help/page.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
import CuratorHelpClient from './CuratorHelpClient';
|
||||
|
||||
export default function CuratorHelpPage() {
|
||||
return <CuratorHelpClient />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user