@@ -25,6 +25,7 @@ import { Button } from '@cdnmanager/ui/components/button'
import { Input } from '@cdnmanager/ui/components/input'
import { Label } from '@cdnmanager/ui/components/label'
import { SelectField } from '@/components/select-field'
import { countrySelectLabel } from '@/lib/country-labels'
import { queryClient } from '@/lib/query-client'
import {
createNode ,
@@ -80,6 +81,7 @@ function NodesPage() {
const [ editing , setEditing ] = useState < Node | null > ( null )
const [ deleteId , setDeleteId ] = useState < string | null > ( null )
const [ preview , setPreview ] = useState ( '' )
const [ countryCode , setCountryCode ] = useState ( '' )
const form = useForm < FormValues > ( {
resolver : zodResolver ( formSchema ) ,
@@ -102,6 +104,30 @@ function NodesPage() {
const watchIndex = form . watch ( 'indexNum' )
const watchProvider = form . watch ( 'providerTag' )
const countryOptions = useMemo ( ( ) = > {
const codes = new Set < string > ( )
for ( const loc of locations ) {
if ( loc . country ) codes . add ( loc . country )
}
return [ . . . codes ]
. sort ( ( a , b ) = > a . localeCompare ( b ) )
. map ( ( code ) = > ( { value : code , label : countrySelectLabel ( code ) } ) )
} , [ locations ] )
const locationOptions = useMemo ( ( ) = > {
if ( ! countryCode ) return [ ]
return locations
. filter ( ( l ) = > l . country === countryCode )
. map ( ( l ) = > ( {
value : l.id ,
label : ` ${ l . code } — ${ l . name } ` ,
} ) )
} , [ locations , countryCode ] )
function countryForLocationId ( locationId : string ) : string {
return locations . find ( ( l ) = > l . id === locationId ) ? . country ? ? ''
}
async function refreshPreview() {
if ( ! watchZone || ! watchLoc || ! watchRole ) return
try {
@@ -148,6 +174,7 @@ function NodesPage() {
toast . success ( editing ? 'Нода обновлена' : 'Нода создана' )
setSheetOpen ( false )
setEditing ( null )
setCountryCode ( '' )
form . reset ( )
void qc . invalidateQueries ( { queryKey : [ 'fleet' ] } )
} ,
@@ -267,6 +294,7 @@ function NodesPage() {
onClick = { ( ) = > {
const n = row . original
setEditing ( n )
setCountryCode ( countryForLocationId ( n . locationId ) )
form . reset ( {
zoneId : n.zoneId ,
locationId : n.locationId ,
@@ -306,9 +334,11 @@ function NodesPage() {
size = "sm"
onClick = { ( ) = > {
setEditing ( null )
const firstLoc = locations [ 0 ]
setCountryCode ( firstLoc ? . country ? ? '' )
form . reset ( {
zoneId : zones [ 0 ] ? . id ? ? '' ,
locationId : locations [ 0 ] ? . id ? ? '' ,
locationId : firstLoc?.id ? ? '' ,
role : 'gw' ,
indexNum : 1 ,
ipv4 : '' ,
@@ -396,20 +426,41 @@ function NodesPage() {
< / div >
) : null }
< div className = "flex flex -col gap-2 " >
< Label > Л о к а ц и я < / Label >
< SelectField
value = { form . watch ( 'locationId' ) }
onValueChange = { ( v ) = > {
form . setValue ( 'locationId' , v ? ? '' )
void refreshPreview ( )
} }
placeholder = "Локация"
options = { locations . map ( ( l ) = > ( {
value : l.id ,
label : ` ${ l . code } — ${ l . name } ` ,
} ) ) }
/ >
< div className = "grid grid -cols-2 gap-3 " >
< div className = "flex flex-col gap-2" >
< Label > С т р а н а < / Label >
< SelectField
value = { countryCode || null }
onValueChange = { ( v ) = > {
const next = v ? ? ''
setCountryCode ( next )
const currentLoc = locations . find ( ( l ) = > l . id === form . getValues ( 'locationId' ) )
if ( ! next || ! currentLoc || currentLoc . country !== next ) {
form . setValue ( 'locationId' , '' )
setPreview ( '' )
}
void refreshPreview ( )
} }
placeholder = "Страна"
options = { countryOptions }
/ >
< / div >
< div className = "flex flex-col gap-2" >
< Label > Л о к а ц и я < / Label >
< SelectField
value = { form . watch ( 'locationId' ) || null }
disabled = { ! countryCode }
onValueChange = { ( v ) = > {
const id = v ? ? ''
form . setValue ( 'locationId' , id )
const loc = locations . find ( ( l ) = > l . id === id )
if ( loc ? . country ) setCountryCode ( loc . country )
void refreshPreview ( )
} }
placeholder = { countryCode ? 'Локация' : 'Сначала страна' }
options = { locationOptions }
/ >
< / div >
< / div >
< div className = "grid grid-cols-2 gap-3" >