Jede Liste gehoert einem Spieler, CC-Guthaben wird umgewandelt
Ein Gruppen-CC wird fuer jeden Nutzer einzeln gerechnet: fuer den einen kann er der gekaufte Platz sein, fuer den anderen ein Redesign seines vorherigen CCs. Dafuer haengt die Liste jetzt an der Mitgliedschaft statt am CC, und verschieben ordnet nur die eigene Liste. Ein Redesign wird nie aus dem CC-Topf bezahlt. Wer sein CC-Guthaben dafuer einsetzt, wandelt es um: ein Platz weniger, ein bezahltes Redesign mehr. Damit entfaellt die Ausnahme, die sich bisher durch Slot-Pruefung und Kettenrechnung zog. Beim Start werden Buchungen einmalig an die Listen angeglichen.
This commit is contained in:
@@ -219,7 +219,10 @@ export default function ChainView({
|
||||
if (!ja) return;
|
||||
setMeldung(null);
|
||||
try {
|
||||
await api(`/api/characters/${character.id}/detach`, { method: 'POST', body: {} });
|
||||
await api(`/api/characters/${character.id}/detach`, {
|
||||
method: 'POST',
|
||||
body: { forPlayerId: playerId },
|
||||
});
|
||||
onMoved();
|
||||
} catch (err) {
|
||||
setMeldung(err instanceof ApiError ? err.message : 'Herauslösen fehlgeschlagen');
|
||||
|
||||
@@ -26,7 +26,10 @@ export function ClassifyModal({
|
||||
const [name, setName] = useState(thread.title);
|
||||
const [predecessorId, setPredecessorId] = useState<number | null>(null);
|
||||
const [reviveId, setReviveId] = useState<number | null>(null);
|
||||
const [useKind, setUseKind] = useState<'REDESIGN_KULANZ' | 'REDESIGN_PAID'>('REDESIGN_KULANZ');
|
||||
// Der Regelfall ist das bezahlte Redesign. Kulanz ist die Ausnahme und
|
||||
// wird bewusst vergeben - sonst entstehen Kulanz-Buchungen, die niemand
|
||||
// gewollt hat.
|
||||
const [useKind, setUseKind] = useState<'REDESIGN_KULANZ' | 'REDESIGN_PAID'>('REDESIGN_PAID');
|
||||
const [characters, setCharacters] = useState<Character[]>([]);
|
||||
const [inactive, setInactive] = useState<Character[]>([]);
|
||||
const [busy, setBusy] = useState(false);
|
||||
@@ -167,19 +170,19 @@ export function ClassifyModal({
|
||||
<input
|
||||
type="radio"
|
||||
name="reviveKind"
|
||||
checked={useKind === 'REDESIGN_KULANZ'}
|
||||
onChange={() => setUseKind('REDESIGN_KULANZ')}
|
||||
checked={useKind === 'REDESIGN_PAID'}
|
||||
onChange={() => setUseKind('REDESIGN_PAID')}
|
||||
/>
|
||||
<span>Kulanz-Redesign</span>
|
||||
<span>Bezahltes Redesign</span>
|
||||
</label>
|
||||
<label className="radio">
|
||||
<input
|
||||
type="radio"
|
||||
name="reviveKind"
|
||||
checked={useKind === 'REDESIGN_PAID'}
|
||||
onChange={() => setUseKind('REDESIGN_PAID')}
|
||||
checked={useKind === 'REDESIGN_KULANZ'}
|
||||
onChange={() => setUseKind('REDESIGN_KULANZ')}
|
||||
/>
|
||||
<span>Bezahltes Redesign</span>
|
||||
<span>Kulanz-Redesign</span>
|
||||
</label>
|
||||
</div>
|
||||
</>
|
||||
@@ -213,19 +216,19 @@ export function ClassifyModal({
|
||||
<input
|
||||
type="radio"
|
||||
name="useKind"
|
||||
checked={useKind === 'REDESIGN_KULANZ'}
|
||||
onChange={() => setUseKind('REDESIGN_KULANZ')}
|
||||
checked={useKind === 'REDESIGN_PAID'}
|
||||
onChange={() => setUseKind('REDESIGN_PAID')}
|
||||
/>
|
||||
<span>Kulanz-Redesign</span>
|
||||
<span>Bezahltes Redesign</span>
|
||||
</label>
|
||||
<label className="radio">
|
||||
<input
|
||||
type="radio"
|
||||
name="useKind"
|
||||
checked={useKind === 'REDESIGN_PAID'}
|
||||
onChange={() => setUseKind('REDESIGN_PAID')}
|
||||
checked={useKind === 'REDESIGN_KULANZ'}
|
||||
onChange={() => setUseKind('REDESIGN_KULANZ')}
|
||||
/>
|
||||
<span>Bezahltes Redesign</span>
|
||||
<span>Kulanz-Redesign</span>
|
||||
</label>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -13,6 +13,7 @@ export const SOURCE_LABEL: Record<CreditSource, string> = {
|
||||
CC_GRANT: 'CC-Guthaben (von Hand)',
|
||||
KULANZ: 'Kulanz',
|
||||
ADJUSTMENT: 'Korrektur',
|
||||
CONVERSION: 'Umwandlung',
|
||||
CONSUME: 'Verbrauch',
|
||||
REVERSAL: 'Storno',
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ export type CreditSource =
|
||||
| 'CC_GRANT'
|
||||
| 'KULANZ'
|
||||
| 'ADJUSTMENT'
|
||||
| 'CONVERSION'
|
||||
| 'CONSUME'
|
||||
| 'REVERSAL';
|
||||
export type CharacterStatus = 'ACTIVE' | 'INACTIVE';
|
||||
|
||||
@@ -601,7 +601,7 @@ export default function PlayerDetail() {
|
||||
submitLabel="Redesign durchführen"
|
||||
hint={`"${dialog.character.name}" wird inaktiv (redesignt), der neue CC tritt an seine Stelle.`}
|
||||
busy={busy}
|
||||
withKind={['REDESIGN_KULANZ', 'REDESIGN_PAID', 'CC']}
|
||||
withKind={['REDESIGN_PAID', 'REDESIGN_KULANZ', 'CC']}
|
||||
balances={detail.balances}
|
||||
onClose={() => setDialog({ type: 'none' })}
|
||||
onSubmit={(values) =>
|
||||
@@ -666,7 +666,7 @@ export default function PlayerDetail() {
|
||||
submitLabel="Redesign durchführen"
|
||||
hint={`${playerName} steigt aus "${dialog.character.name}" aus und bekommt dafür einen eigenen CC. Die übrigen Nutzer bleiben unberührt. Ein Redesign tauscht einen Platz, es kommt keiner hinzu.`}
|
||||
busy={busy}
|
||||
withKind={['REDESIGN_KULANZ', 'REDESIGN_PAID', 'CC']}
|
||||
withKind={['REDESIGN_PAID', 'REDESIGN_KULANZ', 'CC']}
|
||||
balances={detail.balances}
|
||||
onClose={() => setDialog({ type: 'none' })}
|
||||
onSubmit={(values) =>
|
||||
@@ -1069,6 +1069,12 @@ function CharacterFormModal({
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
{useKind === 'CC' && (
|
||||
<p className="muted small">
|
||||
Ein CC-Guthaben für ein Redesign wird umgewandelt: ein Platz weniger, ein
|
||||
bezahltes Redesign mehr.
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user