lomavuokraus/app/listings/mine/page.tsx
2025-12-21 21:58:08 +02:00

124 lines
4 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import Link from 'next/link';
import { useI18n } from '../../components/I18nProvider';
type MyListing = {
id: string;
status: string;
translations: { title: string; slug: string; locale: string }[];
};
export default function MyListingsPage() {
const { t } = useI18n();
const [listings, setListings] = useState<MyListing[]>([]);
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
const [message, setMessage] = useState<string | null>(null);
const [actionId, setActionId] = useState<string | null>(null);
useEffect(() => {
fetch('/api/listings/mine', { cache: 'no-store' })
.then((res) => res.json())
.then((data) => {
if (data.error) {
setError(data.error);
} else {
setListings(data.listings ?? []);
}
})
.catch(() => setError('Failed to load'))
.finally(() => setLoading(false));
}, []);
async function removeListing(listingId: string) {
if (!window.confirm(t('removeConfirm'))) return;
setActionId(listingId);
setError(null);
setMessage(null);
try {
const res = await fetch('/api/listings/remove', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ listingId }),
});
const data = await res.json();
if (!res.ok) {
setError(data.error || 'Failed to remove listing');
} else {
setMessage(t('removed'));
setListings((prev) => prev.map((l) => (l.id === listingId ? { ...l, status: 'REMOVED' } : l)));
}
} catch (e) {
setError('Failed to remove listing');
} finally {
setActionId(null);
}
}
if (loading) {
return (
<main className="panel" style={{ maxWidth: 720, margin: '40px auto' }}>
<h1>{t('myListingsTitle')}</h1>
<p>{t('loading')}</p>
</main>
);
}
if (error) {
return (
<main className="panel" style={{ maxWidth: 720, margin: '40px auto' }}>
<h1>{t('myListingsTitle')}</h1>
<p style={{ color: 'red' }}>{error}</p>
</main>
);
}
return (
<main className="panel" style={{ maxWidth: 720, margin: '40px auto' }}>
<h1>{t('myListingsTitle')}</h1>
{message ? <p style={{ color: 'green' }}>{message}</p> : null}
<div style={{ marginBottom: 12 }}>
<Link href="/listings/new" className="button secondary">
{t('createNewListing')}
</Link>
</div>
{listings.length === 0 ? (
<p>
{t('noListings')}{' '}
<Link href="/listings/new">
{t('createOne')}
</Link>
.
</p>
) : (
<ul style={{ listStyle: 'none', padding: 0, display: 'grid', gap: 10 }}>
{listings.map((l) => (
<li key={l.id} style={{ border: '1px solid #ddd', borderRadius: 8, padding: 12 }}>
<div>
<strong>{l.translations[0]?.title ?? 'Listing'}</strong> {t('statusLabel')}: {l.status}
</div>
<div style={{ fontSize: 12, color: '#666' }}>
{t('slugsLabel')}: {l.translations.map((t) => `${t.slug} (${t.locale})`).join(', ')}
</div>
<div style={{ marginTop: 8, display: 'flex', gap: 8 }}>
<Link href={`/listings/edit/${l.id}`} className="button secondary">
{t('edit')}
</Link>
{l.status !== 'DRAFT' ? (
<Link href={`/listings/${l.translations[0]?.slug ?? ''}`} className="button secondary">
{t('view')}
</Link>
) : null}
<button className="button secondary" onClick={() => removeListing(l.id)} disabled={actionId === l.id}>
{actionId === l.id ? t('removing') : t('remove')}
</button>
</div>
</li>
))}
</ul>
)}
</main>
);
}