1
- import { ChevronLeftIcon } from '@radix-ui/react-icons' ;
2
1
import { useWindowSize } from '@uidotdev/usehooks' ;
3
2
import type { LanguageName } from '@uiw/codemirror-extensions-langs' ;
4
3
import CodeMirror from '@uiw/react-codemirror' ;
5
4
import { Bot , User } from 'lucide-react' ;
6
- import { useMemo , useState } from 'react' ;
5
+ import { useEffect , useMemo , useState } from 'react' ;
7
6
8
7
import { Button } from '@/components/ui/button' ;
9
8
import { Label } from '@/components/ui/label' ;
@@ -18,25 +17,32 @@ import { Skeleton } from '@/components/ui/skeleton';
18
17
import { getTheme , type IEditorTheme , languages , themeOptions } from '@/lib/editor/extensions' ;
19
18
import { useCollab } from '@/lib/hooks/use-collab' ;
20
19
20
+ import { CompleteDialog } from './room/complete-dialog' ;
21
+ import { OtherUserCompletingDialog } from './room/other-user-completing-dialog' ;
22
+
21
23
const EXTENSION_HEIGHT = 250 ;
22
24
const MIN_EDITOR_HEIGHT = 350 ;
23
25
24
26
type EditorProps = {
27
+ questionId : number ;
25
28
room : string ;
26
29
onAIClick : ( ) => void ;
27
30
onPartnerClick : ( ) => void ;
28
31
} ;
29
32
30
- export const Editor = ( { room, onAIClick, onPartnerClick } : EditorProps ) => {
33
+ export const Editor = ( { questionId , room, onAIClick, onPartnerClick } : EditorProps ) => {
31
34
const { height } = useWindowSize ( ) ;
32
35
const [ theme , setTheme ] = useState < IEditorTheme > ( 'vscodeDark' ) ;
33
36
const {
37
+ userId,
34
38
editorRef,
35
39
extensions,
36
40
language,
37
41
setLanguage,
38
42
code,
39
43
setCode,
44
+ isCompleting,
45
+ setIsCompleting,
40
46
cursorPosition,
41
47
members,
42
48
isLoading,
@@ -45,8 +51,19 @@ export const Editor = ({ room, onAIClick, onPartnerClick }: EditorProps) => {
45
51
return getTheme ( theme ) ;
46
52
} , [ theme ] ) ;
47
53
54
+ const [ isOtherUserCompletingDialogOpen , setIsOtherUserCompletingDialogOpen ] = useState ( '' ) ;
55
+
56
+ useEffect ( ( ) => {
57
+ if ( isCompleting . userId !== userId && isCompleting . state ) {
58
+ setIsOtherUserCompletingDialogOpen ( isCompleting . state ) ;
59
+ } else {
60
+ setIsOtherUserCompletingDialogOpen ( '' ) ;
61
+ }
62
+ } , [ isCompleting ] ) ;
63
+
48
64
return (
49
65
< div className = 'flex w-full flex-col gap-4 p-4' >
66
+ { isOtherUserCompletingDialogOpen && < OtherUserCompletingDialog /> }
50
67
{ isLoading ? (
51
68
< div className = 'flex h-[60px] w-full flex-row justify-between pt-3' >
52
69
< div className = 'flex h-10 flex-row gap-4' >
@@ -93,42 +110,47 @@ export const Editor = ({ room, onAIClick, onPartnerClick }: EditorProps) => {
93
110
</ div >
94
111
</ div >
95
112
< div className = 'flex items-center gap-2' >
96
- < div className = 'flex gap-1 font-mono text-xs' >
97
- { /* TODO: Get user avatar and display */ }
98
- { members . map ( ( member , index ) => (
99
- < div
100
- className = 'grid size-8 place-items-center !overflow-clip rounded-full border-2 p-1 text-xs'
101
- style = { {
102
- borderColor : member . color ,
103
- } }
104
- key = { index }
105
- >
106
- < span className = 'translate-x-[calc(-50%+12px)]' > { member . userId } </ span >
107
- </ div >
108
- ) ) }
113
+ < div className = 'flex flex-row gap-2' >
114
+ < div className = 'flex gap-1 font-mono text-xs' >
115
+ { /* TODO: Get user avatar and display */ }
116
+ { members . map ( ( member , index ) => (
117
+ < div
118
+ className = 'grid size-8 place-items-center !overflow-clip rounded-full border-2 p-1 text-xs'
119
+ style = { {
120
+ borderColor : member . color ,
121
+ } }
122
+ key = { index }
123
+ >
124
+ < span className = 'translate-x-[calc(-50%+12px)]' > { member . userId } </ span >
125
+ </ div >
126
+ ) ) }
127
+ </ div >
128
+ </ div >
129
+ < CompleteDialog { ...{ setCompleting : setIsCompleting , questionId, code, members } } >
130
+ < Button size = 'sm' variant = 'destructive' disabled = { ! code } className = 'mx-4' >
131
+ Complete question
132
+ </ Button >
133
+ </ CompleteDialog >
134
+ < div className = 'flex flex-row gap-2' >
135
+ < Button
136
+ variant = 'outline'
137
+ size = 'sm'
138
+ className = 'group flex items-center !px-2 !py-1'
139
+ onClick = { onAIClick }
140
+ >
141
+ < Bot className = 'mr-1 size-4' />
142
+ < span > AI Assistant</ span >
143
+ </ Button >
144
+ < Button
145
+ variant = 'outline'
146
+ size = 'sm'
147
+ className = 'group flex items-center !px-2 !py-1'
148
+ onClick = { onPartnerClick }
149
+ >
150
+ < User className = 'mr-1 size-4' />
151
+ < span > Chat</ span >
152
+ </ Button >
109
153
</ div >
110
- < Button
111
- variant = 'outline'
112
- size = 'sm'
113
- className = 'group flex items-center !px-2 !py-1'
114
- onClick = { onAIClick }
115
- >
116
- < Bot className = 'mr-1 size-4' />
117
- < span > AI Assistant</ span >
118
- </ Button >
119
- < Button
120
- variant = 'outline'
121
- size = 'sm'
122
- className = 'group flex items-center !px-2 !py-1'
123
- onClick = { onPartnerClick }
124
- >
125
- < User className = 'mr-1 size-4' />
126
- < span > Chat</ span >
127
- </ Button >
128
- < Button variant = 'destructive' size = 'sm' className = 'group flex items-center !px-2 !py-1' >
129
- < ChevronLeftIcon className = 'transition-transform duration-200 ease-in-out group-hover:-translate-x-px' />
130
- < span > Disconnect</ span >
131
- </ Button >
132
154
</ div >
133
155
</ div >
134
156
) }
0 commit comments