Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
健杭 徐
intern_project_frontend_backend
Commits
2be90194
Commit
2be90194
authored
Aug 27, 2025
by
健杭 徐
Browse files
finish all
parent
c48b7d0f
Changes
9
Hide whitespace changes
Inline
Side-by-side
myproject/chatroom/main.go
View file @
2be90194
...
@@ -98,15 +98,56 @@ func main() {
...
@@ -98,15 +98,56 @@ func main() {
c
.
Next
()
c
.
Next
()
})
})
router
.
POST
(
"/register"
,
Register
)
router
.
POST
(
"/login"
,
Login
)
router
.
POST
(
"/room/add"
,
AddNewRoom
)
router
.
POST
(
"/room/add"
,
AddNewRoom
)
router
.
GET
(
"/room/list"
,
GetRoomList
)
router
.
GET
(
"/room/list"
,
GetRoomList
)
router
.
POST
(
"/room/delete"
,
DeleteRoom
)
router
.
POST
(
"/room/delete"
,
DeleteRoom
)
router
.
POST
(
"/room/message/add"
,
AddMessage
)
router
.
POST
(
"/room/message/add"
,
AddMessage
)
router
.
GET
(
"/room/message/list"
,
GetMessageList
)
router
.
GET
(
"/room/message/list"
,
GetMessageList
)
router
.
PUT
(
"/room/message/update"
,
RoomMessageUpdate
)
router
.
PUT
(
"/room/message/update"
,
RoomMessageUpdate
)
router
.
PUT
(
"/room/rename"
,
RoomRename
)
router
.
Run
(
":8080"
)
router
.
Run
(
":8080"
)
}
}
func
Register
(
c
*
gin
.
Context
)
{
userName
:=
c
.
Query
(
"userName"
)
password
:=
c
.
Query
(
"password"
)
var
roomId
int
err
:=
db
.
QueryRow
(
"INSERT INTO users (username, password) VALUES ($1, $2) RETURNING user_id"
,
userName
,
password
,
)
.
Scan
(
&
roomId
)
if
err
!=
nil
{
c
.
JSON
(
500
,
Response
{
Code
:
500
,
Msg
:
"注册失败"
,
Data
:
nil
})
return
}
log
.
Printf
(
"New user registered: %s with ID %d"
,
userName
,
roomId
)
c
.
JSON
(
200
,
Response
{
Code
:
0
,
Msg
:
"注册成功"
,
Data
:
nil
})
}
func
Login
(
c
*
gin
.
Context
)
{
userName
:=
c
.
Query
(
"userName"
)
password
:=
c
.
Query
(
"password"
)
var
userId
int
err
:=
db
.
QueryRow
(
"SELECT user_id FROM users WHERE username = $1 AND password = $2"
,
userName
,
password
,
)
.
Scan
(
&
userId
)
if
err
!=
nil
{
c
.
JSON
(
401
,
Response
{
Code
:
401
,
Msg
:
"账号或密码错误"
,
Data
:
nil
})
return
}
log
.
Printf
(
"User logged in: %s with ID %d"
,
userName
,
userId
)
c
.
JSON
(
200
,
Response
{
Code
:
0
,
Msg
:
"登录成功"
,
Data
:
nil
})
}
func
AddNewRoom
(
c
*
gin
.
Context
)
{
func
AddNewRoom
(
c
*
gin
.
Context
)
{
var
room
RoomPreviewInfo
var
room
RoomPreviewInfo
if
err
:=
c
.
ShouldBindJSON
(
&
room
);
err
!=
nil
{
if
err
:=
c
.
ShouldBindJSON
(
&
room
);
err
!=
nil
{
...
@@ -186,27 +227,27 @@ func GetRoomList(c *gin.Context) {
...
@@ -186,27 +227,27 @@ func GetRoomList(c *gin.Context) {
}
}
func
DeleteRoom
(
c
*
gin
.
Context
)
{
func
DeleteRoom
(
c
*
gin
.
Context
)
{
roomId
,
err
:=
strconv
.
Atoi
((
c
.
Query
(
"room
T
d"
)
))
roomId
:=
c
.
Query
(
"room
I
d"
)
if
err
!=
nil
||
roomId
<
=
0
{
if
roomId
=
=
""
{
c
.
JSON
(
http
.
StatusOK
,
Response
{
Code
:
400
,
Msg
:
"
Invalid ID"
})
c
.
JSON
(
400
,
Response
{
Code
:
400
,
Msg
:
"
Room ID is required"
,
Data
:
nil
})
return
return
}
}
result
,
err
:=
db
.
Exec
(
"DELETE FROM
room
s WHERE room
I
d = $1"
,
roomId
)
_
,
err
:=
db
.
Exec
(
"DELETE FROM
message
s WHERE room
_i
d = $1"
,
roomId
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
Response
{
Code
:
500
,
Msg
:
err
.
Error
()
})
c
.
JSON
(
500
,
Response
{
Code
:
500
,
Msg
:
"Failed to delete messages in room: "
+
err
.
Error
(),
Data
:
nil
})
return
return
}
}
rowsAffected
,
_
:=
result
.
RowsAffected
(
)
_
,
err_
:=
db
.
Exec
(
"DELETE FROM rooms WHERE room_id = $1"
,
roomId
)
if
rowsAffected
==
0
{
if
err_
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
Response
{
Code
:
4
00
,
Msg
:
"
Room not found"
})
c
.
JSON
(
500
,
Response
{
Code
:
5
00
,
Msg
:
"
Failed to delete room: "
+
err_
.
Error
(),
Data
:
nil
})
return
return
}
}
c
.
JSON
(
http
.
StatusOK
,
Response
{
c
.
JSON
(
200
,
Response
{
Code
:
0
,
Code
:
0
,
Msg
:
"Room deleted"
,
Msg
:
"Room deleted
successfully
"
,
Data
:
nil
,
Data
:
nil
,
})
})
}
}
...
@@ -287,6 +328,34 @@ func GetMessageList(c *gin.Context) {
...
@@ -287,6 +328,34 @@ func GetMessageList(c *gin.Context) {
})
})
}
}
func
RoomRename
(
c
*
gin
.
Context
)
{
roomId
,
err
:=
strconv
.
Atoi
(
c
.
Query
(
"roomId"
))
if
err
!=
nil
||
roomId
<=
0
{
c
.
JSON
(
http
.
StatusOK
,
Response
{
Code
:
400
,
Msg
:
"Invalid room ID"
})
return
}
var
newName
struct
{
RoomName
string
`json:"roomName"`
}
if
err
:=
c
.
ShouldBindJSON
(
&
newName
);
err
!=
nil
{
c
.
JSON
(
http
.
StatusBadRequest
,
Response
{
Code
:
400
,
Msg
:
"Invalid input: "
+
err
.
Error
(),
Data
:
nil
})
return
}
_
,
err
=
db
.
Exec
(
"UPDATE rooms SET room_name = $1 WHERE room_id = $2"
,
newName
.
RoomName
,
roomId
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusInternalServerError
,
Response
{
Code
:
500
,
Msg
:
"Failed to rename room: "
+
err
.
Error
(),
Data
:
nil
})
return
}
c
.
JSON
(
http
.
StatusOK
,
Response
{
Code
:
0
,
Msg
:
"Room renamed successfully"
,
Data
:
nil
,
})
}
func
RoomMessageUpdate
(
c
*
gin
.
Context
)
{
func
RoomMessageUpdate
(
c
*
gin
.
Context
)
{
// 处理更新房间消息的逻辑
// 处理更新房间消息的逻辑
}
}
...
@@ -310,6 +379,12 @@ func createTable() {
...
@@ -310,6 +379,12 @@ func createTable() {
"time" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
"time" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (room_id) REFERENCES rooms(room_id)
FOREIGN KEY (room_id) REFERENCES rooms(room_id)
);
);
CREATE TABLE IF NOT EXISTS users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(100) NOT NULL
);
`
`
_
,
err
:=
db
.
Exec
(
query
)
_
,
err
:=
db
.
Exec
(
query
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
myproject/my-app/src/app/
pages/
ChatRoom/ChatRoom.css
→
myproject/my-app/src/app/ChatRoom/ChatRoom.
module.
css
View file @
2be90194
...
@@ -100,6 +100,7 @@
...
@@ -100,6 +100,7 @@
margin-bottom
:
10px
;
margin-bottom
:
10px
;
border-radius
:
8px
;
border-radius
:
8px
;
cursor
:
pointer
;
cursor
:
pointer
;
border
:
1px
solid
#ddd
;
&:hover
{
&:hover
{
background-color
:
#e0e0e0
;
background-color
:
#e0e0e0
;
...
@@ -150,6 +151,53 @@
...
@@ -150,6 +151,53 @@
bottom
:
10px
;
bottom
:
10px
;
}
}
}
}
.chat-room-menu
{
position
:
absolute
;
right
:
10px
;
top
:
10px
;
width
:
20px
;
background-color
:
white
;
border
:
1px
solid
#ddd
;
border-radius
:
5px
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0.1
);
z-index
:
100
;
text-align
:
center
;
cursor
:
pointer
;
}
/* Dropdown menu for actions */
.menu-dropdown
{
position
:
absolute
;
right
:
6px
;
top
:
36px
;
min-width
:
160px
;
background
:
#ffffff
;
border
:
1px
solid
#e5e7eb
;
border-radius
:
8px
;
box-shadow
:
0
8px
24px
rgba
(
0
,
0
,
0
,
0.12
);
padding
:
6px
0
;
display
:
none
;
}
.menu-open
{
display
:
block
;
}
.menu-item
{
width
:
100%
;
background
:
transparent
;
border
:
none
;
text-align
:
left
;
padding
:
10px
12px
;
font-size
:
14px
;
color
:
#111827
;
cursor
:
pointer
;
}
.menu-item
:hover
{
background
:
#f3f4f6
;
}
}
}
}
}
...
@@ -161,7 +209,7 @@
...
@@ -161,7 +209,7 @@
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
background-image
:
url('../
../
public/backGround.jpg')
;
background-image
:
url('../public/backGround.jpg')
;
background-size
:
cover
;
background-size
:
cover
;
z-index
:
2
;
z-index
:
2
;
...
...
myproject/my-app/src/app/
pages/
ChatRoom/
ChatRoom
.tsx
→
myproject/my-app/src/app/ChatRoom/
page
.tsx
View file @
2be90194
'
use client
'
;
'
use client
'
;
import
"
./ChatRoom.css
"
;
import
styles
from
"
./ChatRoom.
module.
css
"
;
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
useRouter
}
from
'
next/navigation
'
;
const
backEnd
:
string
=
"
http://localhost:8080
"
;
const
backEnd
:
string
=
"
http://localhost:8080
"
;
...
@@ -33,27 +34,66 @@ interface MessageProps {
...
@@ -33,27 +34,66 @@ interface MessageProps {
}
>
;
}
>
;
}
}
function
RoomEntry
({
rooms
,
onRoomClick
}
:
{
rooms
:
RoomEntryProps
[],
onRoomClick
:
(
roomId
:
number
,
roomName
:
string
)
=>
void
})
{
function
RoomEntry
({
rooms
,
onRoomClick
,
onRename
,
onDelete
}
:
{
rooms
:
RoomEntryProps
[],
onRoomClick
:
(
roomId
:
number
,
roomName
:
string
)
=>
void
,
onRename
:
(
roomId
:
number
,
currentName
:
string
)
=>
void
,
onDelete
:
(
roomId
:
number
)
=>
void
})
{
const
[
openMenuFor
,
setOpenMenuFor
]
=
useState
<
number
|
null
>
(
null
);
useEffect
(()
=>
{
const
handleClickOutside
=
(
e
:
MouseEvent
)
=>
{
const
target
=
e
.
target
as
HTMLElement
;
if
(
!
target
.
closest
(
'
[data-menu="room-actions"]
'
))
{
setOpenMenuFor
(
null
);
}
};
document
.
addEventListener
(
'
click
'
,
handleClickOutside
);
return
()
=>
document
.
removeEventListener
(
'
click
'
,
handleClickOutside
);
},
[]);
return
(
return
(
<
div
className
=
"chat-room-nav"
>
<
div
className
=
{
styles
[
"
chat-room-nav
"
]
}
>
<
div
className
=
"sidebar-action"
>
<
div
className
=
{
styles
[
"
sidebar-action
"
]
}
>
<
button
type
=
"button"
className
=
"button"
onClick
=
{
openOpenDiv
}
>
<
button
type
=
"button"
className
=
{
styles
[
"
button
"
]
}
onClick
=
{
openOpenDiv
}
>
<
div
className
=
"button-top"
>
New Chat
</
div
>
<
div
className
=
{
styles
[
"
button-top
"
]
}
>
New Chat
</
div
>
<
div
className
=
"button-bottom"
></
div
>
<
div
className
=
{
styles
[
"
button-bottom
"
]
}
></
div
>
<
div
className
=
"button-base"
></
div
>
<
div
className
=
{
styles
[
"
button-base
"
]
}
></
div
>
</
button
>
</
button
>
</
div
>
</
div
>
<
div
className
=
"chat-list"
>
<
div
className
=
{
styles
[
"
chat-list
"
]
}
>
{
rooms
.
map
((
room
)
=>
(
{
rooms
.
map
((
room
)
=>
(
<
div
className
=
"chat-item"
key
=
{
room
.
roomId
}
onClick
=
{
()
=>
onRoomClick
(
room
.
roomId
,
room
.
roomName
)
}
>
<
div
className
=
{
styles
[
"
chat-item
"
]
}
key
=
{
room
.
roomId
}
>
<
img
src
=
{
RoomProfile
}
alt
=
"Avatar"
className
=
"avatar"
/>
<
img
src
=
{
RoomProfile
}
alt
=
"Avatar"
className
=
{
styles
[
"
avatar
"
]
}
/>
<
div
className
=
"chat-info"
>
<
div
className
=
{
styles
[
"
chat-info
"
]
}
>
<
h3
>
{
room
.
roomName
}
</
h3
>
<
h3
onClick
=
{
()
=>
onRoomClick
(
room
.
roomId
,
room
.
roomName
)
}
>
{
room
.
roomName
}
</
h3
>
<
span
className
=
"chat-message"
>
<
span
className
=
{
styles
[
"
chat-message
"
]
}
>
{
room
.
lastSender
.
Valid
?
room
.
lastSender
.
String
:
''
}
:
{
room
.
lastSender
.
Valid
?
room
.
lastSender
.
String
:
''
}
:
{
room
.
lastContent
.
Valid
?
room
.
lastContent
.
String
:
''
}
</
span
>
{
room
.
lastContent
.
Valid
?
room
.
lastContent
.
String
:
''
}
</
span
>
<
span
className
=
"chat-time"
>
{
room
.
lastTime
.
Valid
?
formatTimeToHoursMinutes
(
room
.
lastTime
.
Time
)
:
''
}
</
span
>
<
span
className
=
{
styles
[
"
chat-time
"
]
}
>
{
room
.
lastTime
.
Valid
?
formatTimeToHoursMinutes
(
room
.
lastTime
.
Time
)
:
''
}
</
span
>
</
div
>
<
div
className
=
{
styles
[
"
chat-room-menu
"
]
}
data-menu
=
"room-actions"
onClick
=
{
(
e
)
=>
{
e
.
stopPropagation
();
setOpenMenuFor
(
prev
=>
(
prev
===
room
.
roomId
?
null
:
room
.
roomId
));
}
}
aria-label
=
"Room actions"
title
=
"Room actions"
>
···
<
div
className
=
{
`
${
styles
[
"
menu-dropdown
"
]}
${
openMenuFor
===
room
.
roomId
?
styles
[
"
menu-open
"
]
:
''
}
`
}
>
<
button
className
=
{
styles
[
"
menu-item
"
]
}
onClick
=
{
(
e
)
=>
{
e
.
stopPropagation
();
setOpenMenuFor
(
null
);
onRename
(
room
.
roomId
,
room
.
roomName
);
}
}
>
Rename room
</
button
>
<
button
className
=
{
styles
[
"
menu-item
"
]
}
onClick
=
{
(
e
)
=>
{
e
.
stopPropagation
();
setOpenMenuFor
(
null
);
onDelete
(
room
.
roomId
);
}
}
>
Delete room
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
))
}
))
}
...
@@ -65,8 +105,8 @@ function RoomEntry ({rooms, onRoomClick} : {rooms: RoomEntryProps[], onRoomClick
...
@@ -65,8 +105,8 @@ function RoomEntry ({rooms, onRoomClick} : {rooms: RoomEntryProps[], onRoomClick
function
formatTimeToHoursMinutes
(
isoString
:
string
)
{
function
formatTimeToHoursMinutes
(
isoString
:
string
)
{
const
date
=
new
Date
(
isoString
);
const
date
=
new
Date
(
isoString
);
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'
0
'
);
// 确保两位数
const
hours
=
String
(
date
.
getHours
()).
padStart
(
2
,
'
0
'
);
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'
0
'
);
// 确保两位数
const
minutes
=
String
(
date
.
getMinutes
()).
padStart
(
2
,
'
0
'
);
return
`
${
hours
}
:
${
minutes
}
`
;
return
`
${
hours
}
:
${
minutes
}
`
;
}
}
...
@@ -79,12 +119,12 @@ function InputRoomNameArea({ onAddNewRoom }: { onAddNewRoom: (roomName: string)
...
@@ -79,12 +119,12 @@ function InputRoomNameArea({ onAddNewRoom }: { onAddNewRoom: (roomName: string)
closeOpenDiv
();
closeOpenDiv
();
}
}
return
(
return
(
<
div
className
=
"open"
>
<
div
className
=
{
styles
[
"
open
"
]
}
>
<
div
className
=
"roomName-input"
>
<
div
className
=
{
styles
[
"
roomName-input
"
]
}
>
<
h3
>
Please Enter the New Room Name
</
h3
>
<
h3
>
Please Enter the New Room Name
</
h3
>
<
input
<
input
type
=
"text"
type
=
"text"
className
=
"RoomNameInput"
className
=
{
styles
[
"
RoomNameInput
"
]
}
placeholder
=
"Start new chat"
placeholder
=
"Start new chat"
value
=
{
roomNameInput
}
value
=
{
roomNameInput
}
onChange
=
{
(
e
)
=>
setRoomNameInput
(
e
.
target
.
value
)
}
onChange
=
{
(
e
)
=>
setRoomNameInput
(
e
.
target
.
value
)
}
...
@@ -97,9 +137,9 @@ function InputRoomNameArea({ onAddNewRoom }: { onAddNewRoom: (roomName: string)
...
@@ -97,9 +137,9 @@ function InputRoomNameArea({ onAddNewRoom }: { onAddNewRoom: (roomName: string)
}
}
}
}
}
}
/>
/>
<
div
className
=
"button-container"
>
<
div
className
=
{
styles
[
"
button-container
"
]
}
>
<
button
className
=
"create-button"
onClick
=
{
handleAddNewRoom
}
>
Submit
</
button
>
<
button
className
=
{
styles
[
"
create-button
"
]
}
onClick
=
{
handleAddNewRoom
}
>
Submit
</
button
>
<
button
className
=
"cancel-button"
onClick
=
{
closeOpenDiv
}
>
Cancel
</
button
>
<
button
className
=
{
styles
[
"
cancel-button
"
]
}
onClick
=
{
closeOpenDiv
}
>
Cancel
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -107,25 +147,33 @@ function InputRoomNameArea({ onAddNewRoom }: { onAddNewRoom: (roomName: string)
...
@@ -107,25 +147,33 @@ function InputRoomNameArea({ onAddNewRoom }: { onAddNewRoom: (roomName: string)
}
}
function
openOpenDiv
()
{
function
openOpenDiv
()
{
const
openDiv
=
document
.
getElementsByClassName
(
"
open
"
)[
0
]
as
HTMLDivElement
;
const
openDiv
=
document
.
getElementsByClassName
(
styles
.
open
)[
0
]
as
HTMLDivElement
|
undefined
;
openDiv
.
style
.
zIndex
=
"
1000
"
;
if
(
openDiv
)
{
const
roomNameInput
=
document
.
getElementsByClassName
(
"
RoomNameInput
"
)[
0
]
as
HTMLInputElement
;
openDiv
.
style
.
zIndex
=
"
1000
"
;
roomNameInput
.
style
.
zIndex
=
"
1001
"
;
}
const
roomNameInput
=
document
.
getElementsByClassName
(
styles
.
RoomNameInput
)[
0
]
as
HTMLInputElement
|
undefined
;
if
(
roomNameInput
)
{
roomNameInput
.
style
.
zIndex
=
"
1001
"
;
}
}
}
function
closeOpenDiv
()
{
function
closeOpenDiv
()
{
const
openDiv
=
document
.
getElementsByClassName
(
"
open
"
)[
0
]
as
HTMLDivElement
;
const
openDiv
=
document
.
getElementsByClassName
(
styles
.
open
)[
0
]
as
HTMLDivElement
|
undefined
;
openDiv
.
style
.
zIndex
=
"
0
"
;
if
(
openDiv
)
{
const
roomNameInput
=
document
.
getElementsByClassName
(
"
RoomNameInput
"
)[
0
]
as
HTMLInputElement
;
openDiv
.
style
.
zIndex
=
"
0
"
;
roomNameInput
.
style
.
zIndex
=
"
0
"
;
}
(
document
.
getElementsByClassName
(
"
RoomNameInput
"
)[
0
]
as
HTMLInputElement
).
value
=
''
;
const
roomNameInput
=
document
.
getElementsByClassName
(
styles
.
RoomNameInput
)[
0
]
as
HTMLInputElement
|
undefined
;
if
(
roomNameInput
)
{
roomNameInput
.
style
.
zIndex
=
"
0
"
;
roomNameInput
.
value
=
''
;
}
}
}
function
MessageItem
(
props
:
MessageProps
&
{
onAddNewComment
:
(
content
:
string
)
=>
void
})
{
function
MessageItem
(
props
:
MessageProps
&
{
onAddNewComment
:
(
content
:
string
)
=>
void
})
{
const
[
inputValue
,
setInputValue
]
=
useState
(
""
);
const
[
inputValue
,
setInputValue
]
=
useState
(
""
);
if
(
props
.
roomId
===
0
)
{
if
(
props
.
roomId
===
0
)
{
return
<
div
className
=
"message-item"
>
Please select a room to chat.
</
div
>;
return
<
div
className
=
{
styles
[
"
message-item
"
]
}
>
Please select a room to chat.
</
div
>;
}
}
const
handlerSend
=
()
=>
{
const
handlerSend
=
()
=>
{
...
@@ -137,31 +185,31 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string)
...
@@ -137,31 +185,31 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string)
setInputValue
(
''
);
setInputValue
(
''
);
}
}
return
(
return
(
<
div
className
=
"message-item"
>
<
div
className
=
{
styles
[
"
message-item
"
]
}
>
<
div
className
=
"message-header"
>
<
div
className
=
{
styles
[
"
message-header
"
]
}
>
<
img
src
=
{
RoomProfile
}
alt
=
"Avatar"
className
=
"avatar"
/>
<
img
src
=
{
RoomProfile
}
alt
=
"Avatar"
className
=
{
styles
[
"
avatar
"
]
}
/>
<
h2
>
{
props
.
roomName
}
</
h2
>
<
h2
>
{
props
.
roomName
}
</
h2
>
</
div
>
</
div
>
<
div
className
=
"message-list"
>
<
div
className
=
{
styles
[
"
message-list
"
]
}
>
{
props
.
messages
.
map
((
msg
,
index
)
=>
(
{
props
.
messages
.
map
((
msg
,
index
)
=>
(
<
div
key
=
{
index
}
className
=
"message"
>
<
div
key
=
{
index
}
className
=
{
styles
[
"
message
"
]
}
>
<
img
src
=
{
Profile
[
msg
.
profile
]
}
alt
=
{
`
${
msg
.
sender
}
's avatar`
}
className
=
"avatar"
/>
<
img
src
=
{
Profile
[
msg
.
profile
]
}
alt
=
{
`
${
msg
.
sender
}
's avatar`
}
className
=
{
styles
[
"
avatar
"
]
}
/>
<
div
className
=
"message-content"
>
<
div
className
=
{
styles
[
"
message-content
"
]
}
>
<
div
className
=
"message-info"
>
<
div
className
=
{
styles
[
"
message-info
"
]
}
>
<
span
className
=
"message-sender"
>
{
msg
.
sender
}
</
span
>
<
span
className
=
{
styles
[
"
message-sender
"
]
}
>
{
msg
.
sender
}
</
span
>
<
span
className
=
"message-time"
>
{
formatTimeToHoursMinutes
(
msg
.
time
)
}
</
span
>
<
span
className
=
{
styles
[
"
message-time
"
]
}
>
{
formatTimeToHoursMinutes
(
msg
.
time
)
}
</
span
>
</
div
>
</
div
>
<
p
className
=
"message-text"
>
{
msg
.
content
}
</
p
>
<
p
className
=
{
styles
[
"
message-text
"
]
}
>
{
msg
.
content
}
</
p
>
</
div
>
</
div
>
</
div
>
</
div
>
))
}
))
}
</
div
>
</
div
>
<
div
className
=
"message-input"
>
<
div
className
=
{
styles
[
"
message-input
"
]
}
>
<
input
<
input
type
=
"text"
type
=
"text"
placeholder
=
"Type a message..."
placeholder
=
"Type a message..."
className
=
"Inputarea"
className
=
{
styles
[
"
Inputarea
"
]
}
value
=
{
inputValue
}
value
=
{
inputValue
}
onChange
=
{
(
e
)
=>
setInputValue
(
e
.
target
.
value
)
}
onChange
=
{
(
e
)
=>
setInputValue
(
e
.
target
.
value
)
}
onKeyUpCapture
=
{
onKeyUpCapture
=
{
(
e
:
React
.
KeyboardEvent
<
HTMLInputElement
>
)
=>
{
(
e
:
React
.
KeyboardEvent
<
HTMLInputElement
>
)
=>
{
...
@@ -169,9 +217,9 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string)
...
@@ -169,9 +217,9 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string)
handlerSend
();
handlerSend
();
}
}
}
}
/>
}
}
/>
<
button
className
=
"send-button"
onClick
=
{
handlerSend
}
>
<
button
className
=
{
styles
[
"
send-button
"
]
}
onClick
=
{
handlerSend
}
>
<
div
className
=
"svg-wrapper-1"
>
<
div
className
=
{
styles
[
"
svg-wrapper-1
"
]
}
>
<
div
className
=
"svg-wrapper"
>
<
div
className
=
{
styles
[
"
svg-wrapper
"
]
}
>
<
svg
<
svg
xmlns
=
"http://www.w3.org/2000/svg"
xmlns
=
"http://www.w3.org/2000/svg"
viewBox
=
"0 0 24 24"
viewBox
=
"0 0 24 24"
...
@@ -194,31 +242,72 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string)
...
@@ -194,31 +242,72 @@ function MessageItem (props: MessageProps & { onAddNewComment: (content: string)
// From Uiverse.io by adamgiebl
// From Uiverse.io by adamgiebl
}
}
export
function
ChatRoom
({
userName
}:
{
userName
:
string
})
{
export
function
ChatRoom
Component
({
userName
}:
{
userName
:
string
})
{
const
[
rooms
,
setRooms
]
=
useState
<
RoomEntryProps
[]
>
([]);
const
[
rooms
,
setRooms
]
=
useState
<
RoomEntryProps
[]
>
([]);
const
[
currentRoom
,
setCurrentRoom
]
=
useState
<
MessageProps
|
null
>
(
null
);
const
[
currentRoom
,
setCurrentRoom
]
=
useState
<
MessageProps
|
null
>
(
null
);
const
ROOM_LIST_REFRESH_INTERVAL
=
1000
;
const
MESSAGE_REFRESH_INTERVAL
=
1000
;
useEffect
(()
=>
{
const
fetchRooms
=
async
()
=>
{
const
fetchRooms
=
async
()
=>
{
try
{
try
{
const
response
=
await
fetch
(
backEnd
+
"
/room/list
"
);
const
response
=
await
fetch
(
backEnd
+
"
/room/list
"
);
const
result
=
await
response
.
json
();
const
result
=
await
response
.
json
();
if
(
result
.
code
===
0
)
{
const
ferchedRooms
=
result
.
data
.
map
((
room
:
any
)
=>
({
...
room
,
lastSender
:
room
.
lastSender
||
{
String
:
''
,
Valid
:
false
},
laseComment
:
room
.
lastComment
||
{
String
:
''
,
Valid
:
false
},
lastTime
:
room
.
lastTime
||
{
String
:
''
,
Valid
:
false
}
}));
setRooms
(
ferchedRooms
);
}
}
catch
(
error
)
{
console
.
error
(
"
Error fetching rooms:
"
,
error
);
}
};
const
fetchCurrentRoomMessages
=
async
(
roomId
:
number
)
=>
{
if
(
!
roomId
)
return
;
try
{
const
response
=
await
fetch
(
backEnd
+
`/room/message/list?roomId=
${
roomId
}
`
);
const
result
=
await
response
.
json
();
if
(
result
.
code
===
0
)
{
if
(
result
.
code
===
0
)
{
const
ferchedRooms
=
result
.
data
.
map
((
room
:
any
)
=>
({
setCurrentRoom
(
prev
=>
{
...
room
,
if
(
!
prev
||
prev
.
roomId
!==
roomId
)
return
prev
;
lastSender
:
room
.
lastSender
||
{
String
:
''
,
Valid
:
false
},
return
{
laseComment
:
room
.
lastComment
||
{
String
:
''
,
Valid
:
false
},
...
prev
,
lastTime
:
room
.
lastTime
||
{
String
:
''
,
Valid
:
false
}
messages
:
result
.
data
||
[]
}));
};
setRooms
(
ferchedRooms
);
});
}
}
catch
(
error
)
{
console
.
error
(
"
Error fetching rooms:
"
,
error
);
}
}
}
catch
(
error
)
{
console
.
error
(
"
Error fetching messages:
"
,
error
);
}
}
};
useEffect
(()
=>
{
fetchRooms
();
fetchRooms
();
const
roomListInterval
=
setInterval
(()
=>
{
fetchRooms
();
},
ROOM_LIST_REFRESH_INTERVAL
);
return
()
=>
clearInterval
(
roomListInterval
);
},
[]);
},
[]);
useEffect
(()
=>
{
if
(
!
currentRoom
?.
roomId
)
return
;
const
messageInterval
=
setInterval
(()
=>
{
fetchCurrentRoomMessages
(
currentRoom
.
roomId
);
},
MESSAGE_REFRESH_INTERVAL
);
return
()
=>
clearInterval
(
messageInterval
);
},
[
currentRoom
?.
roomId
]);
const
handleRoomClick
=
async
(
roomId
:
number
,
roomName
:
string
)
=>
{
const
handleRoomClick
=
async
(
roomId
:
number
,
roomName
:
string
)
=>
{
setCurrentRoom
({
setCurrentRoom
({
roomId
:
roomId
,
roomId
:
roomId
,
...
@@ -226,28 +315,7 @@ export function ChatRoom({ userName }: { userName: string }) {
...
@@ -226,28 +315,7 @@ export function ChatRoom({ userName }: { userName: string }) {
messages
:
[]
messages
:
[]
});
});
try
{
await
fetchCurrentRoomMessages
(
roomId
);
const
response
=
await
fetch
(
backEnd
+
`/room/message/list?roomId=
${
roomId
}
`
)
const
result
=
await
response
.
json
();
debugger
;
if
(
result
.
code
===
0
)
{
setCurrentRoom
({
roomId
:
roomId
,
roomName
:
roomName
,
messages
:
result
.
data
||
[]
});
}
else
{
alert
(
`Error fetching messages:
${
result
.
msg
}
`
);
setCurrentRoom
({
roomId
:
roomId
,
roomName
:
roomName
,
messages
:
[]
});
}
}
catch
(
error
){
console
.
error
(
"
Error fetching messages:
"
,
error
);
alert
(
"
Failed to fetch messages. See console for details.
"
);
}
}
}
async
function
addNewRoom
(
roomName
:
string
)
{
async
function
addNewRoom
(
roomName
:
string
)
{
...
@@ -334,9 +402,51 @@ export function ChatRoom({ userName }: { userName: string }) {
...
@@ -334,9 +402,51 @@ export function ChatRoom({ userName }: { userName: string }) {
}
}
}
}
const
handleRename
=
async
(
roomId
:
number
,
currentName
:
string
)
=>
{
const
newName
=
prompt
(
'
Enter new room name
'
,
currentName
);
if
(
!
newName
||
newName
.
trim
()
===
''
||
newName
===
currentName
)
return
;
try
{
const
response
=
await
fetch
(
backEnd
+
'
/room/rename
'
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
},
body
:
JSON
.
stringify
({
roomId
,
roomName
:
newName
})
});
const
result
=
await
response
.
json
();
if
(
result
.
code
!==
0
)
{
alert
(
'
Rename failed:
'
+
(
result
.
msg
||
'
unknown error
'
));
return
;
}
setRooms
(
prev
=>
prev
.
map
(
r
=>
r
.
roomId
===
roomId
?
{
...
r
,
roomName
:
newName
}
:
r
));
setCurrentRoom
(
prev
=>
prev
&&
prev
.
roomId
===
roomId
?
{
...
prev
,
roomName
:
newName
}
:
prev
);
}
catch
(
err
)
{
console
.
error
(
'
Rename error
'
,
err
);
alert
(
'
Rename error
'
);
}
};
const
handleDelete
=
async
(
roomId
:
number
)
=>
{
if
(
!
confirm
(
'
Delete this room? This cannot be undone.
'
))
return
;
try
{
const
response
=
await
fetch
(
backEnd
+
'
/room/delete?roomId=
'
+
roomId
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
},
});
const
result
=
await
response
.
json
();
if
(
result
.
code
!==
0
)
{
alert
(
'
Delete failed:
'
+
(
result
.
msg
||
'
unknown error
'
));
return
;
}
setRooms
(
prev
=>
prev
.
filter
(
r
=>
r
.
roomId
!==
roomId
));
setCurrentRoom
(
prev
=>
(
prev
&&
prev
.
roomId
===
roomId
)
?
null
:
prev
);
}
catch
(
err
)
{
console
.
error
(
'
Delete error
'
,
err
);
alert
(
'
Delete error
'
);
}
};
return
(
return
(
<
div
className
=
"chat-room"
>
<
div
className
=
{
styles
[
"
chat-room
"
]
}
>
<
RoomEntry
rooms
=
{
rooms
}
onRoomClick
=
{
handleRoomClick
}
/>
<
RoomEntry
rooms
=
{
rooms
}
onRoomClick
=
{
handleRoomClick
}
onRename
=
{
handleRename
}
onDelete
=
{
handleDelete
}
/>
<
MessageItem
<
MessageItem
roomId
=
{
currentRoom
?.
roomId
||
0
}
roomId
=
{
currentRoom
?.
roomId
||
0
}
roomName
=
{
currentRoom
?.
roomName
||
""
}
roomName
=
{
currentRoom
?.
roomName
||
""
}
...
@@ -346,4 +456,24 @@ export function ChatRoom({ userName }: { userName: string }) {
...
@@ -346,4 +456,24 @@ export function ChatRoom({ userName }: { userName: string }) {
<
InputRoomNameArea
onAddNewRoom
=
{
addNewRoom
}
/>
<
InputRoomNameArea
onAddNewRoom
=
{
addNewRoom
}
/>
</
div
>
</
div
>
);
);
}
export
default
function
ChatRoom
()
{
const
[
userName
,
setUserName
]
=
useState
<
string
|
null
>
(
null
);
const
router
=
useRouter
();
useEffect
(()
=>
{
const
storedUserName
=
localStorage
.
getItem
(
'
userName
'
);
if
(
storedUserName
)
{
setUserName
(
storedUserName
);
}
else
{
router
.
push
(
'
/
'
);
}
},
[
router
]);
if
(
!
userName
)
{
return
<
div
>
Loading...
</
div
>;
}
return
<
ChatRoomComponent
userName
=
{
userName
}
/>;
}
}
\ No newline at end of file
myproject/my-app/src/app/
pages/SetName/SetNam
e.css
→
myproject/my-app/src/app/
Register/Register.modul
e.css
View file @
2be90194
*
/
*
{
{
margin: 0;
margin: 0;
padding: 0;
padding: 0;
box-sizing: border-box;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
font-family: 'Poppins', sans-serif;
}
}
*/
.SetName-Body
.SetName-Body
{
{
...
@@ -16,7 +16,7 @@
...
@@ -16,7 +16,7 @@
min-height
:
100vh
;
min-height
:
100vh
;
width
:
100vw
;
width
:
100vw
;
background-size
:
cover
;
background-size
:
cover
;
background
:
url('../
../
public/SetbackGround.jpg')
no-repeat
center
;
background
:
url('../public/SetbackGround.jpg')
no-repeat
center
;
}
}
.login-box
.login-box
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
backdrop-filter
:
blur
(
15px
);
backdrop-filter
:
blur
(
15px
);
}
}
h2
.setname-
h2
{
{
font-size
:
2em
;
font-size
:
2em
;
color
:
white
;
color
:
white
;
...
@@ -73,7 +73,7 @@ h2
...
@@ -73,7 +73,7 @@ h2
border
:
none
;
border
:
none
;
outline
:
none
;
outline
:
none
;
background-color
:
transparent
;
background-color
:
transparent
;
color
:
white
;
color
:
black
;
font-size
:
1em
;
font-size
:
1em
;
padding
:
0
35px
0
5px
;
padding
:
0
35px
0
5px
;
}
}
...
@@ -105,3 +105,10 @@ h2
...
@@ -105,3 +105,10 @@ h2
{
{
background-color
:
lightgray
;
background-color
:
lightgray
;
}
}
.setname-repeat
{
font-size
:
.9em
;
color
:
white
;
margin
:
20px
0
10px
0
;
}
\ No newline at end of file
myproject/my-app/src/app/Register/page.tsx
0 → 100644
View file @
2be90194
'
use client
'
;
import
styles
from
"
./Register.module.css
"
import
{
MdLock
,
MdPerson
}
from
"
react-icons/md
"
;
import
{
useState
}
from
"
react
"
;
const
backEnd
:
string
=
"
http://localhost:8080
"
;
export
default
function
Register
({
onLogin
}:
{
onLogin
:
(
name
:
string
)
=>
void
})
{
const
[
userName
,
setUserName
]
=
useState
(
''
);
const
[
password
,
setPassword
]
=
useState
(
''
);
const
[
confirmPassword
,
setConfirmPassword
]
=
useState
(
''
);
const
[
passwordError
,
setPasswordError
]
=
useState
(
''
);
const
handleSubmit
=
async
(
e
:
React
.
FormEvent
)
=>
{
e
.
preventDefault
();
setPasswordError
(
''
);
if
(
password
!==
confirmPassword
)
{
setPasswordError
(
'
Passwords do not match
'
);
return
;
}
if
(
password
.
length
<
6
)
{
setPasswordError
(
'
Password must be at least 6 characters
'
);
return
;
}
try
{
const
response
=
await
fetch
(
backEnd
+
'
/register
'
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
},
body
:
JSON
.
stringify
({
userName
,
password
}),
});
if
(
!
response
.
ok
)
{
throw
new
Error
(
'
Failed to register
'
);
}
const
data
=
await
response
.
json
();
onLogin
(
data
.
userName
);
}
catch
(
error
)
{
console
.
error
(
error
);
}
}
return
(
<
div
className
=
{
styles
[
"
SetName-Body
"
]
}
>
<
div
className
=
{
styles
[
"
login-box
"
]
}
>
<
form
onSubmit
=
{
handleSubmit
}
>
<
h2
className
=
{
styles
[
"
setname-h2
"
]
}
>
Register
</
h2
>
<
div
className
=
{
styles
[
"
input-box
"
]
}
>
<
span
className
=
{
styles
[
"
icon
"
]
}
>
<
MdPerson
/>
</
span
>
<
input
required
value
=
{
userName
}
onChange
=
{
(
e
)
=>
setUserName
(
e
.
target
.
value
)
}
/>
<
label
>
Name
</
label
>
</
div
>
<
div
className
=
{
styles
[
"
input-box
"
]
}
>
<
span
className
=
{
styles
[
"
icon
"
]
}
>
<
MdLock
/>
</
span
>
<
input
type
=
"password"
required
value
=
{
password
}
onChange
=
{
(
e
)
=>
setPassword
(
e
.
target
.
value
)
}
/>
<
label
>
Password
</
label
>
</
div
>
<
div
className
=
{
styles
[
"
input-box
"
]
}
>
<
span
className
=
{
styles
[
"
icon
"
]
}
>
<
MdLock
/>
</
span
>
<
input
type
=
"password"
required
value
=
{
confirmPassword
}
onChange
=
{
(
e
)
=>
setConfirmPassword
(
e
.
target
.
value
)
}
/>
<
label
>
Confirm Password
</
label
>
</
div
>
{
passwordError
&&
(
<
div
style
=
{
{
color
:
'
red
'
,
fontSize
:
'
14px
'
,
marginTop
:
'
5px
'
,
textAlign
:
'
center
'
}
}
>
{
passwordError
}
</
div
>
)
}
<
div
>
<
button
className
=
{
styles
[
"
SetName-button
"
]
}
type
=
"submit"
>
Register
</
button
>
</
div
>
</
form
>
</
div
>
</
div
>
);
}
\ No newline at end of file
myproject/my-app/src/app/SetName/SetName.module.css
0 → 100644
View file @
2be90194
/*
{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
} */
.SetName-Body
{
z-index
:
2000
;
display
:
flex
;
position
:
absolute
;
justify-content
:
center
;
align-items
:
center
;
min-height
:
100vh
;
width
:
100vw
;
background-size
:
cover
;
background
:
url('../public/SetbackGround.jpg')
no-repeat
center
;
}
.login-box
{
position
:
relative
;
width
:
400px
;
height
:
450px
;
background-color
:
transparent
;
border
:
2px
solid
rgba
(
255
,
255
,
255
,
.5
);
border-radius
:
20px
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
backdrop-filter
:
blur
(
15px
);
}
.setname-h2
{
font-size
:
2em
;
color
:
white
;
text-align
:
center
;
}
.input-box
{
position
:
relative
;
width
:
310px
;
margin
:
30px
0
;
border-bottom
:
2px
solid
white
;
}
.input-box
label
{
position
:
absolute
;
top
:
50%
;
left
:
5px
;
transform
:
translateY
(
-50%
);
font-size
:
1em
;
color
:
white
;
pointer-events
:
none
;
transition
:
.5s
;
}
.input-box
input
:focus
~
label
,
.input-box
input
:valid
~
label
{
top
:
-5px
;
}
.input-box
input
{
width
:
100%
;
height
:
50px
;
border
:
none
;
outline
:
none
;
background-color
:
transparent
;
color
:
black
;
font-size
:
1em
;
padding
:
0
35px
0
5px
;
}
.input-box
.icon
{
position
:
absolute
;
right
:
8px
;
color
:
white
;
font-size
:
.9em
;
line-height
:
57px
;
}
.SetName-button
{
outline
:
none
;
border
:
none
;
width
:
100%
;
height
:
50px
;
background-color
:
white
;
border-radius
:
40px
;
cursor
:
pointer
;
color
:
black
;
font-size
:
1em
;
font-weight
:
bold
;
}
.SetName-button
:hover
{
background-color
:
lightgray
;
}
.register_link
{
font-size
:
.9em
;
text-align
:
center
;
color
:
white
;
margin
:
20px
0
10px
0
;
a
{
text-decoration
:
none
;
color
:
white
;
font-weight
:
600
;
}
a
:hover
{
text-decoration
:
underline
;
}
}
\ No newline at end of file
myproject/my-app/src/app/SetName/page.tsx
0 → 100644
View file @
2be90194
'
use client
'
;
import
styles
from
"
./SetName.module.css
"
import
{
MdLock
,
MdPerson
}
from
"
react-icons/md
"
;
import
{
useState
}
from
"
react
"
;
import
Link
from
"
next/link
"
;
const
backEnd
:
string
=
"
http://localhost:8080
"
;
export
default
function
SetName
({
onLogin
}:
{
onLogin
:
(
name
:
string
)
=>
void
})
{
const
[
userName
,
setUserName
]
=
useState
(
''
);
const
[
password
,
setPassword
]
=
useState
(
''
);
const
handleSubmit
=
async
(
e
:
React
.
FormEvent
)
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
try
{
const
response
=
await
fetch
(
`
${
backEnd
}
/login`
,
{
method
:
"
POST
"
,
headers
:
{
"
Content-Type
"
:
"
application/json
"
},
body
:
JSON
.
stringify
({
userName
,
password
})
});
const
data
=
await
response
.
json
();
if
(
data
.
code
===
0
)
{
onLogin
(
userName
);
}
else
{
alert
(
data
.
msg
);
}
}
catch
(
error
)
{
console
.
error
(
"
Error logging in:
"
,
error
);
}
}
return
(
<
div
className
=
{
styles
[
"
SetName-Body
"
]
}
>
<
div
className
=
{
styles
[
"
login-box
"
]
}
>
<
form
onSubmit
=
{
handleSubmit
}
>
<
h2
className
=
{
styles
[
"
setname-h2
"
]
}
>
Login
</
h2
>
<
div
className
=
{
styles
[
"
input-box
"
]
}
>
<
span
className
=
{
styles
[
"
icon
"
]
}
>
<
MdPerson
/>
</
span
>
<
input
required
value
=
{
userName
}
onChange
=
{
(
e
)
=>
setUserName
(
e
.
target
.
value
)
}
/>
<
label
>
Name
</
label
>
</
div
>
<
div
className
=
{
styles
[
"
input-box
"
]
}
>
<
span
className
=
{
styles
[
"
icon
"
]
}
>
<
MdLock
/>
</
span
>
<
input
type
=
"password"
required
value
=
{
password
}
onChange
=
{
(
e
)
=>
setPassword
(
e
.
target
.
value
)
}
/>
<
label
>
Password
</
label
>
</
div
>
<
div
>
<
button
className
=
{
styles
[
"
SetName-button
"
]
}
type
=
"submit"
>
Login in
</
button
>
</
div
>
<
div
className
=
{
styles
[
"
register_link
"
]
}
>
<
p
>
Don't have an account?
<
Link
href
=
"/Register"
>
Register
</
Link
></
p
>
</
div
>
</
form
>
</
div
>
</
div
>
);
}
\ No newline at end of file
myproject/my-app/src/app/page.tsx
View file @
2be90194
'
use client
'
;
'
use client
'
;
import
React
,
{
useState
}
from
'
react
'
;
import
React
from
'
react
'
;
import
{
ChatRoom
}
from
"
./pages/ChatRoom/ChatRoom
"
;
import
SetName
from
'
./SetName/page
'
;
import
{
SetName
}
from
'
./pages/SetName/SetName
'
;
import
"
./globals.css
"
;
import
"
./globals.css
"
;
import
{
useRouter
}
from
'
next/navigation
'
;
export
default
function
Page
()
{
export
default
function
Page
()
{
const
[
userName
,
setUserName
]
=
useState
(
''
);
const
router
=
useRouter
(
);
const
handleLogin
=
(
name
:
string
)
=>
{
const
handleLogin
=
(
name
:
string
)
=>
{
setUserName
(
name
);
localStorage
.
setItem
(
'
userName
'
,
name
);
router
.
push
(
'
/ChatRoom
'
);
};
};
return
(
return
(
<
div
className
=
'root'
>
<
div
className
=
'root'
>
{
!
userName
?
(
<
SetName
onLogin
=
{
handleLogin
}
/>
<
SetName
onLogin
=
{
handleLogin
}
/>
)
:
(
<
ChatRoom
userName
=
{
userName
}
/>
)
}
</
div
>
</
div
>
);
);
}
}
\ No newline at end of file
myproject/my-app/src/app/pages/SetName/SetName.tsx
deleted
100644 → 0
View file @
c48b7d0f
'
use client
'
;
import
"
./SetName.css
"
import
{
MdPerson
}
from
"
react-icons/md
"
;
import
{
useRouter
}
from
"
next/compat/router
"
;
import
{
useState
}
from
"
react
"
;
export
function
SetName
({
onLogin
}:
{
onLogin
:
(
name
:
string
)
=>
void
})
{
const
[
userName
,
setUserName
]
=
useState
(
''
);
const
handleSubmit
=
async
(
e
:
React
.
FormEvent
)
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
if
(
userName
.
trim
())
{
onLogin
(
userName
);
}
}
return
(
<
div
className
=
"SetName-Body"
>
<
div
className
=
"login-box"
>
<
form
onSubmit
=
{
handleSubmit
}
>
<
h2
>
Login
</
h2
>
<
div
className
=
"input-box"
>
<
span
className
=
"icon"
>
<
MdPerson
/>
</
span
>
<
input
required
value
=
{
userName
}
onChange
=
{
(
e
)
=>
setUserName
(
e
.
target
.
value
)
}
/>
<
label
>
Name
</
label
>
</
div
>
<
div
>
<
button
className
=
"SetName-button"
type
=
"submit"
>
Login in
</
button
>
</
div
>
</
form
>
</
div
>
</
div
>
);
}
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment