UNPKG

@basictech/cli

Version:

Basic CLI for creating & managing your projects

193 lines 8.51 kB
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