feat(crew): add a coordinator "Check status" button to the crew form
For a coordinator addressed by pubkey, the form now probes it on demand (the same useCoordinatorHealth the Settings → Coordinator card uses) and shows Connected / Quiet / Not seen / Unreachable. Reuses the existing socialUi .coordinator status copy; no new keys.
This commit is contained in:
parent
3cc16d18ca
commit
c93d7e4e41
1 changed files with 55 additions and 1 deletions
|
|
@ -24,7 +24,7 @@ import { NofferField } from '@/components/NofferField';
|
|||
import { SKATE_CREW_KIND, SKATE_SPOT_KIND, SKATE_SHOP_KIND, parseAddrCoord, ZAP_GOAL_KIND, CREW_VIBE_LABELS, CREW_FOCUS_LABELS, CREW_FOCUS_DESCRIPTIONS, CREW_FOCUS_TAG, CREW_LOOKING_FOR_OPTIONS, CREW_ROLE_META, CREW_ROLE_ORDER, SHOW_CREW_TREASURY, isValidNoffer, type SkateCrew, type CrewFocus, type CrewRole } from '@/lib/types';
|
||||
import { CREW_VIBE_KEYS, CREW_FOCUS_KEYS, CREW_FOCUS_DESC_KEYS, CREW_LOOKING_FOR_KEYS, CREW_ROLE_KEYS } from '@/lib/labelKeys';
|
||||
import { useCrewGoal } from '@/hooks/useCrewGoal';
|
||||
import { useCoordinator } from '@/hooks/useCoordinator';
|
||||
import { useCoordinator, useCoordinatorHealth } from '@/hooks/useCoordinator';
|
||||
import { Nip05HandlesEditor } from '@/components/Nip05HandlesEditor';
|
||||
import { coordinatorAddUrl, crewCoordinatorInputValue, parseCrewCoordinatorInput, shortNpub } from '@/lib/coordinator';
|
||||
import { useRelays } from '@/lib/relays';
|
||||
|
|
@ -191,6 +191,16 @@ interface CrewFormProps {
|
|||
existing?: SkateCrew | null;
|
||||
}
|
||||
|
||||
/** Static map for coordinator health status → i18n key (no dynamic keys). */
|
||||
const HEALTH_LABEL: Record<string, string> = {
|
||||
idle: 'socialUi.coordinator.statusIdle',
|
||||
checking: 'socialUi.coordinator.statusChecking',
|
||||
online: 'socialUi.coordinator.statusOnline',
|
||||
stale: 'socialUi.coordinator.statusStale',
|
||||
offline: 'socialUi.coordinator.statusOffline',
|
||||
error: 'socialUi.coordinator.statusError',
|
||||
};
|
||||
|
||||
export function CrewForm({ existing }: CrewFormProps) {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -295,6 +305,17 @@ export function CrewForm({ existing }: CrewFormProps) {
|
|||
const { coordinator: myCoordinator } = useCoordinator();
|
||||
// Live parse so the founder gets feedback (and the publish path reuses it).
|
||||
const parsedCoordinator = parseCrewCoordinatorInput(coordinatorInput);
|
||||
// On-demand health probe (the "Check" button) for a coordinator addressed by
|
||||
// pubkey — mirrors the Settings → Coordinator card.
|
||||
const coordinatorHealth = useCoordinatorHealth(
|
||||
parsedCoordinator?.pubkey
|
||||
? {
|
||||
pubkey: parsedCoordinator.pubkey,
|
||||
relays: /^wss?:\/\//i.test(parsedCoordinator.url) ? [parsedCoordinator.url] : [],
|
||||
addedAt: 0,
|
||||
}
|
||||
: null,
|
||||
);
|
||||
// Crew video / montage — YouTube or Instagram URL ("The Part").
|
||||
const [videoUrl, setVideoUrl] = useState(existing?.videoUrl ?? '');
|
||||
|
||||
|
|
@ -1154,6 +1175,39 @@ export function CrewForm({ existing }: CrewFormProps) {
|
|||
{t('socialUi.coordinator.useMine')}
|
||||
</Button>
|
||||
)}
|
||||
{parsedCoordinator?.pubkey && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="gap-1.5 border-gray-700 text-gray-300 hover:bg-white/5"
|
||||
onClick={() => coordinatorHealth.check()}
|
||||
disabled={coordinatorHealth.status === 'checking'}
|
||||
>
|
||||
{coordinatorHealth.status === 'checking' ? (
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
||||
) : (
|
||||
<Server className="h-3.5 w-3.5" />
|
||||
)}
|
||||
{t('socialUi.coordinator.check')}
|
||||
</Button>
|
||||
<span
|
||||
className={cn(
|
||||
'text-[11px] font-bold uppercase',
|
||||
coordinatorHealth.status === 'online'
|
||||
? 'text-teal-400'
|
||||
: coordinatorHealth.status === 'stale'
|
||||
? 'text-amber-400'
|
||||
: coordinatorHealth.status === 'error'
|
||||
? 'text-red-400'
|
||||
: 'text-gray-500',
|
||||
)}
|
||||
>
|
||||
{t(HEALTH_LABEL[coordinatorHealth.status] ?? 'socialUi.coordinator.statusIdle')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<p className="text-[10px] leading-snug text-gray-600">{t('socialUi.coordinator.pointerNote')}</p>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue