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 { 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 { 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 { useCrewGoal } from '@/hooks/useCrewGoal';
|
||||||
import { useCoordinator } from '@/hooks/useCoordinator';
|
import { useCoordinator, useCoordinatorHealth } from '@/hooks/useCoordinator';
|
||||||
import { Nip05HandlesEditor } from '@/components/Nip05HandlesEditor';
|
import { Nip05HandlesEditor } from '@/components/Nip05HandlesEditor';
|
||||||
import { coordinatorAddUrl, crewCoordinatorInputValue, parseCrewCoordinatorInput, shortNpub } from '@/lib/coordinator';
|
import { coordinatorAddUrl, crewCoordinatorInputValue, parseCrewCoordinatorInput, shortNpub } from '@/lib/coordinator';
|
||||||
import { useRelays } from '@/lib/relays';
|
import { useRelays } from '@/lib/relays';
|
||||||
|
|
@ -191,6 +191,16 @@ interface CrewFormProps {
|
||||||
existing?: SkateCrew | null;
|
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) {
|
export function CrewForm({ existing }: CrewFormProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
@ -295,6 +305,17 @@ export function CrewForm({ existing }: CrewFormProps) {
|
||||||
const { coordinator: myCoordinator } = useCoordinator();
|
const { coordinator: myCoordinator } = useCoordinator();
|
||||||
// Live parse so the founder gets feedback (and the publish path reuses it).
|
// Live parse so the founder gets feedback (and the publish path reuses it).
|
||||||
const parsedCoordinator = parseCrewCoordinatorInput(coordinatorInput);
|
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").
|
// Crew video / montage — YouTube or Instagram URL ("The Part").
|
||||||
const [videoUrl, setVideoUrl] = useState(existing?.videoUrl ?? '');
|
const [videoUrl, setVideoUrl] = useState(existing?.videoUrl ?? '');
|
||||||
|
|
||||||
|
|
@ -1154,6 +1175,39 @@ export function CrewForm({ existing }: CrewFormProps) {
|
||||||
{t('socialUi.coordinator.useMine')}
|
{t('socialUi.coordinator.useMine')}
|
||||||
</Button>
|
</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>
|
<p className="text-[10px] leading-snug text-gray-600">{t('socialUi.coordinator.pointerNote')}</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue