feat: added reject image and migrated to tailwindcss
feat: made it smartphone friendly
This commit is contained in:
@@ -4,7 +4,22 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import Link from 'next/link';
|
||||
|
||||
import style from '@/styles/admin.module.scss';
|
||||
import {
|
||||
btn,
|
||||
btnDanger,
|
||||
card,
|
||||
error as errorClass,
|
||||
formWide,
|
||||
hr,
|
||||
input,
|
||||
label,
|
||||
metaLine,
|
||||
rowActions,
|
||||
sectionBlock,
|
||||
sectionTitle,
|
||||
textarea,
|
||||
title,
|
||||
} from '@/lib/adminUi';
|
||||
|
||||
type Char = { id: number; name_id: string; name: string; name_jp: string };
|
||||
type PlayerRow = {
|
||||
@@ -18,6 +33,8 @@ type PlayerRow = {
|
||||
name_jp?: string;
|
||||
};
|
||||
|
||||
const field = `${input} ${textarea}`;
|
||||
|
||||
export function PlayersAdminClient() {
|
||||
const [players, setPlayers] = useState<PlayerRow[]>([]);
|
||||
const [characters, setCharacters] = useState<Char[]>([]);
|
||||
@@ -129,60 +146,57 @@ export function PlayersAdminClient() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={style.card}>
|
||||
<div className={card}>
|
||||
<p>
|
||||
<Link href="/admin">← Dashboard</Link>
|
||||
</p>
|
||||
<h1 className={style.title}>Players</h1>
|
||||
{error ? <p className={style.error}>{error}</p> : null}
|
||||
<h1 className={title}>Players</h1>
|
||||
{error ? <p className={errorClass}>{error}</p> : null}
|
||||
{loading ? <p>Loading…</p> : null}
|
||||
{!loading && (
|
||||
<>
|
||||
{players.map((p) => (
|
||||
<div
|
||||
key={p.id}
|
||||
style={{ marginBottom: 24, paddingBottom: 16, borderBottom: '1px solid #eee' }}
|
||||
>
|
||||
<p style={{ margin: '0 0 8px', fontSize: '0.85rem', color: '#666' }}>
|
||||
<div key={p.id} className={sectionBlock}>
|
||||
<p className={metaLine}>
|
||||
id: {p.id}
|
||||
{p.name_jp ? ` · ${p.name_jp}` : ''}
|
||||
</p>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
player_key
|
||||
<input
|
||||
className={style.input}
|
||||
className={input}
|
||||
value={p.player_key}
|
||||
onChange={(e) => updateLocal(p.id, { player_key: e.target.value })}
|
||||
/>
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
player_name
|
||||
<input
|
||||
className={style.input}
|
||||
className={input}
|
||||
value={p.player_name}
|
||||
onChange={(e) => updateLocal(p.id, { player_name: e.target.value })}
|
||||
/>
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
description
|
||||
<textarea
|
||||
className={`${style.input} ${style.textarea}`}
|
||||
className={field}
|
||||
value={p.description ?? ''}
|
||||
onChange={(e) => updateLocal(p.id, { description: e.target.value })}
|
||||
/>
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
image URL (optional)
|
||||
<input
|
||||
className={style.input}
|
||||
className={input}
|
||||
value={p.image ?? ''}
|
||||
onChange={(e) => updateLocal(p.id, { image: e.target.value || null })}
|
||||
/>
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
character
|
||||
<select
|
||||
className={style.input}
|
||||
className={input}
|
||||
value={p.character_id != null && p.character_id !== '' ? String(p.character_id) : ''}
|
||||
onChange={(e) => updateLocal(p.id, { character_id: e.target.value })}
|
||||
required
|
||||
@@ -195,46 +209,40 @@ export function PlayersAdminClient() {
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<div className={style.rowActions}>
|
||||
<button type="button" className={style.btn} onClick={() => save(p)}>
|
||||
<div className={rowActions}>
|
||||
<button type="button" className={btn} onClick={() => save(p)}>
|
||||
Save
|
||||
</button>
|
||||
<button type="button" className={style.btnDanger} onClick={() => remove(p.id)}>
|
||||
<button type="button" className={btnDanger} onClick={() => remove(p.id)}>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<hr className={style.hr} />
|
||||
<h2 className={style.title} style={{ fontSize: '1.1rem' }}>
|
||||
Add player
|
||||
</h2>
|
||||
<form className={style.form} style={{ maxWidth: 480 }} onSubmit={addPlayer}>
|
||||
<label className={style.label}>
|
||||
<hr className={hr} />
|
||||
<h2 className={sectionTitle}>Add player</h2>
|
||||
<form className={formWide} onSubmit={addPlayer}>
|
||||
<label className={label}>
|
||||
player_key
|
||||
<input className={style.input} value={playerKey} onChange={(e) => setPlayerKey(e.target.value)} required />
|
||||
<input className={input} value={playerKey} onChange={(e) => setPlayerKey(e.target.value)} required />
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
player_name
|
||||
<input className={style.input} value={playerName} onChange={(e) => setPlayerName(e.target.value)} required />
|
||||
<input className={input} value={playerName} onChange={(e) => setPlayerName(e.target.value)} required />
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
description
|
||||
<textarea
|
||||
className={`${style.input} ${style.textarea}`}
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
/>
|
||||
<textarea className={field} value={description} onChange={(e) => setDescription(e.target.value)} />
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
image URL (optional)
|
||||
<input className={style.input} value={image} onChange={(e) => setImage(e.target.value)} />
|
||||
<input className={input} value={image} onChange={(e) => setImage(e.target.value)} />
|
||||
</label>
|
||||
<label className={style.label}>
|
||||
<label className={label}>
|
||||
character
|
||||
<select
|
||||
className={style.input}
|
||||
className={input}
|
||||
value={characterId}
|
||||
onChange={(e) => setCharacterId(e.target.value)}
|
||||
required
|
||||
@@ -247,7 +255,7 @@ export function PlayersAdminClient() {
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<button className={style.btn} type="submit">
|
||||
<button className={btn} type="submit">
|
||||
Add
|
||||
</button>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user