@basictech/cli
Version:
Basic CLI for creating & managing your projects
193 lines • 8.51 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect } from 'react';
import { Box, Text, useInput } from 'ink';
import { ApiClient } from '../lib/api.js';
import { generateSlug } from '../lib/platform.js';
export function TeamForm({ title, onSubmit, onCancel }) {
const [state, setState] = useState({
teamName: '',
teamSlug: '',
currentField: 'name',
isCheckingSlug: false,
slugAvailable: null,
error: null
});
// Auto-generate slug when team name changes
useEffect(() => {
if (state.teamName.trim()) {
const newSlug = generateSlug(state.teamName);
setState(prev => ({
...prev,
teamSlug: newSlug,
slugAvailable: null,
error: null
}));
}
else {
setState(prev => ({
...prev,
teamSlug: '',
slugAvailable: null,
error: null
}));
}
}, [state.teamName]);
// Check slug availability when slug changes
useEffect(() => {
if (state.teamSlug.trim() && (state.currentField === 'name' || state.currentField === 'slug')) {
const checkAvailability = async () => {
setState(prev => ({ ...prev, isCheckingSlug: true, error: null }));
try {
const apiClient = ApiClient.getInstance();
const available = await apiClient.checkTeamSlugAvailability(state.teamSlug);
setState(prev => ({
...prev,
isCheckingSlug: false,
slugAvailable: available,
error: available ? null : 'Team slug is already taken'
}));
}
catch (error) {
setState(prev => ({
...prev,
isCheckingSlug: false,
slugAvailable: false,
error: 'Error checking slug availability'
}));
}
};
const timeoutId = setTimeout(checkAvailability, 500); // Debounce for 500ms
return () => clearTimeout(timeoutId);
}
}, [state.teamSlug, state.currentField]);
useInput((input, key) => {
if (state.currentField === 'submitting') {
return; // Don't handle input while submitting
}
if (key.escape) {
onCancel();
return;
}
if (key.return) {
if (state.currentField === 'name') {
// Move to slug editing if team name is provided
if (!state.teamName.trim()) {
setState(prev => ({ ...prev, error: 'Team name is required' }));
return;
}
setState(prev => ({ ...prev, currentField: 'slug', error: null }));
return;
}
if (state.currentField === 'slug') {
// Validate and submit
if (!state.teamSlug.trim()) {
setState(prev => ({ ...prev, error: 'Team slug is required' }));
return;
}
if (!state.slugAvailable) {
setState(prev => ({ ...prev, error: 'Please wait for slug availability check or choose a different name' }));
return;
}
setState(prev => ({ ...prev, currentField: 'submitting', error: null }));
const result = onSubmit({ teamName: state.teamName, teamSlug: state.teamSlug });
if (result instanceof Promise) {
result.catch((error) => {
setState(prev => ({
...prev,
currentField: 'slug',
error: error.message || 'Failed to create team'
}));
});
}
return;
}
}
if (key.backspace || key.delete) {
if (state.currentField === 'name') {
setState(prev => ({
...prev,
teamName: prev.teamName.slice(0, -1),
error: null
}));
}
else if (state.currentField === 'slug') {
setState(prev => ({
...prev,
teamSlug: prev.teamSlug.slice(0, -1),
error: null
}));
}
return;
}
// Add character to current field
if (input && input.length === 1) {
if (state.currentField === 'name') {
setState(prev => ({
...prev,
teamName: prev.teamName + input,
error: null
}));
}
else if (state.currentField === 'slug') {
setState(prev => ({
...prev,
teamSlug: prev.teamSlug + input,
error: null
}));
}
}
});
const getSlugStatus = () => {
if (!state.teamSlug.trim())
return null;
if (state.isCheckingSlug)
return 'checking';
if (state.slugAvailable === true)
return 'available';
if (state.slugAvailable === false)
return 'unavailable';
return null;
};
const getSlugStatusText = () => {
const status = getSlugStatus();
switch (status) {
case 'checking':
return '⏳ Checking availability...';
case 'available':
return '✅ Slug available';
case 'unavailable':
return '❌ Slug not available';
default:
return '';
}
};
const getSlugStatusColor = () => {
const status = getSlugStatus();
switch (status) {
case 'checking':
return 'yellow';
case 'available':
return 'green';
case 'unavailable':
return 'red';
default:
return 'gray';
}
};
const canSubmit = state.teamName.trim() && state.slugAvailable === true && !state.isCheckingSlug;
const getHelpText = () => {
if (state.currentField === 'name') {
return state.teamName.trim()
? 'Enter to edit slug • esc to cancel'
: 'Type team name • esc to cancel';
}
else if (state.currentField === 'slug') {
return canSubmit
? 'Enter to create team • esc to cancel'
: 'Edit team slug • esc to cancel';
}
return 'esc to cancel';
};
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 2, children: _jsx(Text, { bold: true, color: "blue", children: title }) }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: state.currentField === 'name' ? 'blue' : 'gray', children: [state.currentField === 'name' ? '>' : '✓', " Team Name:"] }) }), _jsx(Box, { marginLeft: 2, children: _jsxs(Text, { children: [state.teamName, state.currentField === 'name' && (_jsx(Text, { backgroundColor: "white", color: "black", children: "\u2588" }))] }) })] }), state.teamSlug && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { children: _jsxs(Text, { color: state.currentField === 'slug' ? 'blue' : 'gray', children: [state.currentField === 'slug' ? '>' : '✓', " Team Slug", state.currentField === 'name' ? ' (auto-generated)' : '', ":"] }) }), _jsx(Box, { marginLeft: 2, children: _jsxs(Text, { children: [state.teamSlug, state.currentField === 'slug' && (_jsx(Text, { backgroundColor: "white", color: "black", children: "\u2588" }))] }) }), getSlugStatus() && (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: getSlugStatusColor(), children: getSlugStatusText() }) }))] })), state.error && (_jsx(Box, { marginLeft: 2, marginBottom: 1, children: _jsxs(Text, { color: "red", children: ["Error: ", state.error] }) })), _jsx(Box, { marginTop: 2, children: _jsx(Text, { color: "gray", children: getHelpText() }) })] }));
}
//# sourceMappingURL=TeamForm.js.map