22import React , { useState } from "react" ;
33import { Loader2 , Github , AlertCircle } from "lucide-react" ;
44import { Button } from "../ui/Button" ;
5+ import { SUPPORTED_LANGUAGES } from "@/constants/languages" ;
56
67interface SearchInputProps {
7- onGenerate : ( url : string ) => void ;
8+ onGenerate : ( url : string , language : string ) => void ;
89 isLoading : boolean ;
910 initialValue ?: string ; // optional initial value
1011 ariaLabel ?: string ; // optional aria-label for accessibility
1112}
1213
14+ /**
15+ * SearchInput Component
16+ * Renders a responsive form for GitHub URL input and language selection.
17+ *
18+ * @param {SearchInputProps } props - The component props.
19+ * @returns {JSX.Element } The rendered search input form.
20+ */
1321export const SearchInput = ( {
1422 onGenerate,
1523 isLoading,
@@ -18,6 +26,7 @@ export const SearchInput = ({
1826} : SearchInputProps ) => {
1927 // Initialize state directly from initialValue once
2028 const [ url , setUrl ] = useState ( initialValue || "" ) ;
29+ const [ language , setLanguage ] = useState ( "English" ) ;
2130 const [ error , setError ] = useState < string | null > ( null ) ;
2231
2332 const handleSubmit = ( e : React . FormEvent ) => {
@@ -28,36 +37,59 @@ export const SearchInput = ({
2837 / ^ h t t p s ? : \/ \/ ( w w w \. ) ? g i t h u b \. c o m \/ [ \w . - ] + \/ [ \w . - ] + \/ ? $ / ;
2938
3039 if ( githubUrlPattern . test ( url . trim ( ) ) ) {
31- onGenerate ( url . trim ( ) ) ;
40+ onGenerate ( url . trim ( ) , language ) ;
3241 } else {
3342 setError ( "Please enter a valid GitHub repository URL." ) ;
3443 }
3544 } ;
3645
3746 return (
38- < div className = "w-full max-w-4xl mx-auto" >
39- < form onSubmit = { handleSubmit } className = "relative group" >
40- < div className = "absolute inset-y-0 left-5 flex items-center pointer-events-none text-gray-500 group-focus-within:text-blue-500 transition-colors" >
41- < Github size = { 20 } />
47+ < div className = "w-full max-w-4xl mx-auto space-y-4" >
48+ < form
49+ onSubmit = { handleSubmit }
50+ className = "relative group flex flex-col md:flex-row gap-4"
51+ >
52+ < div className = "relative flex-grow" >
53+ < div className = "absolute inset-y-0 left-5 flex items-center pointer-events-none text-gray-500 group-focus-within:text-blue-500 transition-colors" >
54+ < Github size = { 20 } />
55+ </ div >
56+ < input
57+ type = "text"
58+ value = { url }
59+ onChange = { ( e ) => {
60+ setUrl ( e . target . value ) ;
61+ if ( error ) setError ( null ) ;
62+ } }
63+ placeholder = "https://github.com/username/repo"
64+ aria-label = { ariaLabel }
65+ className = { `w-full bg-zinc-900/50 border ${
66+ error ? "border-red-500/50" : "border-white/10"
67+ } rounded-2xl py-6 pl-14 pr-4 text-white placeholder:text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500/50 transition-all backdrop-blur-xl`}
68+ />
4269 </ div >
43- < input
44- type = "text"
45- value = { url }
46- onChange = { ( e ) => {
47- setUrl ( e . target . value ) ;
48- if ( error ) setError ( null ) ;
49- } }
50- placeholder = "https://github.com/username/repo"
51- aria-label = { ariaLabel }
52- className = { `w-full bg-zinc-900/50 border ${
53- error ? "border-red-500/50" : "border-white/10"
54- } rounded-2xl py-6 pl-14 pr-40 text-white placeholder:text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500/50 transition-all backdrop-blur-xl`}
55- />
56- < div className = "absolute inset-y-2 right-2 flex items-center" >
70+
71+ < div className = "flex gap-4" >
72+ < select
73+ value = { language }
74+ onChange = { ( e ) => setLanguage ( e . target . value ) }
75+ aria-label = "Select language for README generation"
76+ className = "bg-zinc-900/50 border border-white/10 rounded-2xl px-6 py-6 text-white focus:outline-none focus:ring-2 focus:ring-blue-500/50 transition-all backdrop-blur-xl appearance-none cursor-pointer min-w-[140px]"
77+ >
78+ { SUPPORTED_LANGUAGES . map ( ( lang ) => (
79+ < option
80+ key = { lang }
81+ value = { lang }
82+ className = "bg-zinc-900 text-white"
83+ >
84+ { lang }
85+ </ option >
86+ ) ) }
87+ </ select >
88+
5789 < Button
5890 type = "submit"
5991 disabled = { isLoading || ! url }
60- className = "h-full px-8 shadow-lg shadow-blue-500/20"
92+ className = "h-full px-8 shadow-lg shadow-blue-500/20 whitespace-nowrap "
6193 >
6294 { isLoading ? (
6395 < Loader2 className = "animate-spin" size = { 18 } />
0 commit comments