mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 15:51:00 +00:00
71cd6c2de4
A place copied from a collection and a venue a booking import creates now record their details as an import, so a later edit compares against what was really written. Dawarich and the background enrichment write none of the shareable fields, so they need nothing. The admin panel asks again for a few seconds while a fresh installation is still fetching its key, so the prompt appears without a reload.
65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
import type { PlaceContribDecisionRequest, PlaceContribState } from '@trek/shared';
|
|
import { useCallback, useEffect, useState } from 'react';
|
|
import { placeContribRepo } from '../../repo/placeContribRepo';
|
|
|
|
const KEY_RETRIES = 6;
|
|
const KEY_RETRY_MS = 3_000;
|
|
|
|
/**
|
|
* The admin's decision on sharing place details. Read once when the settings
|
|
* tab opens, so the prompt can come up without the card being scrolled to;
|
|
* every decision answers the new state, which replaces the old one.
|
|
*/
|
|
export function usePlaceContrib() {
|
|
const [state, setState] = useState<PlaceContribState | null>(null);
|
|
const [failed, setFailed] = useState(false);
|
|
const [busy, setBusy] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const controller = new AbortController();
|
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
// A fresh installation fetches its key on first use, so the first answer can
|
|
// be no_key; asking again a few times lets the prompt appear once it landed.
|
|
const read = (tries: number) => {
|
|
placeContribRepo.state(controller.signal).then(
|
|
(next) => {
|
|
setState(next);
|
|
if (next.ineligibleReason === 'no_key' && tries > 1) timer = setTimeout(() => read(tries - 1), KEY_RETRY_MS);
|
|
},
|
|
() => {
|
|
if (!controller.signal.aborted) setFailed(true);
|
|
}
|
|
);
|
|
};
|
|
read(KEY_RETRIES);
|
|
return () => {
|
|
controller.abort();
|
|
clearTimeout(timer);
|
|
};
|
|
}, []);
|
|
|
|
const decide = useCallback(async (body: PlaceContribDecisionRequest): Promise<PlaceContribState> => {
|
|
setBusy(true);
|
|
try {
|
|
const next = await placeContribRepo.decide(body);
|
|
setState(next);
|
|
return next;
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}, []);
|
|
|
|
const withdraw = useCallback(async () => {
|
|
setBusy(true);
|
|
try {
|
|
const result = await placeContribRepo.withdraw();
|
|
setState(await placeContribRepo.state());
|
|
return result;
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}, []);
|
|
|
|
return { state, failed, busy, decide, withdraw };
|
|
}
|