1
- import { useEffect , useState } from "react" ;
1
+ import { useEffect , useState , useCallback } from "react" ;
2
2
import './styles.css' ;
3
3
4
+ const LOCATION_NAMES = [ "inn" , "fairy_village" ] ;
5
+ const PLAYER_ID = 0 ;
6
+
4
7
export default function App ( ) {
5
8
const [ message , setMessage ] = useState ( "" ) ;
6
- const [ dialogue , setDialogue ] = useState ( "" ) ;
9
+ const [ dialogue , setDialogue ] = useState ( "" ) ;
7
10
const [ activeCharacter , setActiveCharacter ] = useState ( 0 ) ;
8
11
const [ isSending , setIsSending ] = useState ( false ) ;
9
12
const [ location , setLocation ] = useState ( 0 ) ;
10
13
const [ agentsIds , setAgentsIds ] = useState ( [ ] ) ;
11
14
12
15
const API_URL = import . meta. env . VITE_BACKEND_API_URL ;
13
16
17
+ const locationIdToResourceName = useCallback ( ( id ) => LOCATION_NAMES [ id ] , [ ] ) ;
18
+
14
19
const sendMessage = async ( e ) => {
15
20
if ( e . key === "Enter" && message . trim ( ) ) {
16
- setIsSending ( true ) ;
21
+ setIsSending ( true ) ;
22
+ try {
23
+ const response = await fetch ( `${ API_URL } /say` , {
24
+ method : "POST" ,
25
+ headers : { "Content-Type" : "application/json" } ,
26
+ body : JSON . stringify ( { player_id : PLAYER_ID , agent_id : activeCharacter , message : message } ) ,
27
+ } ) ;
28
+
29
+ if ( ! response . ok ) throw new Error ( `Error: ${ response . status } ` ) ;
30
+
31
+ const data = await response . json ( ) ;
32
+
33
+ setDialogue ( data . message ) ;
34
+ setActiveCharacter ( data . responder_id ) ;
35
+ setMessage ( "" ) ;
36
+ } catch ( error ) {
37
+ console . error ( error ) ;
38
+ } finally {
39
+ setIsSending ( false ) ;
40
+ }
41
+ }
42
+ } ;
17
43
18
- const response = await fetch ( `${ API_URL } /say` , {
44
+ const enterLocation = async ( ) => {
45
+ try {
46
+ const response = await fetch ( `${ API_URL } /enterLocation` , {
19
47
method : "POST" ,
20
48
headers : { "Content-Type" : "application/json" } ,
21
- body : JSON . stringify ( { player_id : 0 , agent_id : activeCharacter , message : message } ) ,
49
+ body : JSON . stringify ( { player_id : PLAYER_ID , location_id : location } ) ,
22
50
} ) ;
23
51
24
52
if ( ! response . ok ) throw new Error ( `Error: ${ response . status } ` ) ;
25
53
26
54
const data = await response . json ( ) ;
55
+ setAgentsIds ( data . agents_ids ) ;
56
+ setActiveCharacter ( data . agents_ids [ 0 ] ) ;
27
57
28
- setDialogue ( data . message ) ;
29
- setActiveCharacter ( data . responder_id ) ;
30
- setMessage ( "" ) ;
31
- setIsSending ( false ) ;
58
+ } catch ( error ) {
59
+ console . error ( error ) ;
32
60
}
33
61
} ;
34
62
35
- const locationIdToResourceName = ( id ) => [ "inn" , "fairy_village" ] [ id ] ;
36
-
37
- useEffect ( ( ) => {
38
- const enterLocation = async ( ) => {
39
- try {
40
- const response = await fetch ( `${ API_URL } /enterLocation` ,
41
- {
42
- method : "POST" ,
43
- headers : { "Content-Type" : "application/json" } ,
44
- body : JSON . stringify ( { player_id : 0 , location_id : location } ) ,
45
- } ) ;
46
-
47
- if ( ! response . ok ) throw new Error ( `Error: ${ response . status } ` ) ;
48
-
49
- const data = await response . json ( ) ;
50
-
51
- setAgentsIds ( data . agents_ids ) ;
52
- setActiveCharacter ( data . agents_ids [ 0 ] ) ;
53
-
54
- } catch ( error ) {
55
- console . error ( error ) ;
56
- }
57
- } ;
63
+ useEffect ( ( ) => {
58
64
enterLocation ( ) ;
59
65
} , [ location ] ) ;
60
66
67
+ const changeLocation = ( ) => {
68
+ setLocation ( ( prevLocation ) => ( prevLocation + 1 ) % LOCATION_NAMES . length ) ;
69
+ setDialogue ( "" ) ;
70
+ }
71
+
61
72
return (
62
73
< div className = "app-container"
63
- style = { { backgroundImage : `url('/images/${ locationIdToResourceName ( location ) } /background.jpg')` } } >
64
- { dialogue ? < div className = "dialogue-box" > { dialogue } </ div > : < > </ > }
74
+ style = { { backgroundImage : `url('/images/${ locationIdToResourceName ( location ) } /background.jpg')` } } >
75
+ { dialogue && < div className = "dialogue-box" > { dialogue } </ div > }
65
76
< div className = "content" >
66
77
{ agentsIds . map ( ( char , i ) => (
67
78
< div key = { char } className = "column" >
68
79
< img
69
80
src = { `/images/${ locationIdToResourceName ( location ) } /character_0${ i + 1 } .png` }
70
81
className = { `character-img ${ activeCharacter === char ? "talking" : "" } ` }
71
82
alt = "Character"
72
- onClick = { ( ) => {
73
- if ( ! isSending ) setActiveCharacter ( char )
74
- } }
83
+ onClick = { ( ) => ! isSending && setActiveCharacter ( char ) }
75
84
/>
76
85
</ div >
77
86
) ) }
@@ -86,9 +95,9 @@ export default function App() {
86
95
/>
87
96
< button
88
97
className = "change-location-button"
89
- onClick = { ( ) => { setLocation ( ( location + 1 ) % 2 ) } }
98
+ onClick = { changeLocation }
90
99
>
91
- { ( location === 0 ) ? "Leave Inn" : "Go back to Inn" }
100
+ { location === 0 ? "Leave Inn" : "Go back to Inn" }
92
101
</ button >
93
102
</ div >
94
103
) ;
0 commit comments