Skip to content

Commit

Permalink
[feat] 환경 설정에서 ID 및 닉네임 수정 & 스트리밍 비밀 키 복사 기능 구현 (#141)
Browse files Browse the repository at this point in the history
* feat : ID 및 닉네임 수정 기능 구현

* feat : 로그인 했을 때만 ID 및 닉네임 수정 가능하게 구현

* feat : 방송 비밀키 클립보드에 복사하는 기능 구현
  • Loading branch information
Novrule authored Dec 6, 2023
1 parent eafd67b commit 2465967
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 64 deletions.
19 changes: 10 additions & 9 deletions client/src/components/Modal/LoginModal/LoginModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,23 @@ interface LoginModalProps {

const LoginModal = ({ onCancle, currentTheme }: LoginModalProps) => {
const onLoginImage = () => {
const popup = window.open('http://localhost:3000/oauth/login/naver', '_blank', 'menubar=no, toolbar=no, width=500, height=600')
const popup = window.open('https://api.gbs-live.site/oauth/login/naver', '_blank', 'menubar=no, toolbar=no, width=500, height=600')

const popupEvent = () => {
if (popup !== null && popup.closed == true) {
fetch('http://localhost:3000/users/me/', { method: 'GET', credentials: 'include' })
.then((req) => {
if (req.ok === true) {
return req.json()
fetch('https://api.gbs-live.site/users/me/', { method: 'GET', credentials: 'include' })
.then((res) => {
if (res.ok === true) {
return res.json()
} else {
throw new Error('Login Failed')
}
})
.then((req) => {
const id = req.userId
const nickname = req.nickname
.then((res) => {
const userId = res.userId
const userNickname = res.nickname

localStorage.setItem('user', JSON.stringify({ id: id, nickname: nickname }))
localStorage.setItem('user', JSON.stringify({ id: userId, nickname: userNickname }))
window.location.reload()
})
.catch((err) => console.error(err))
Expand Down
14 changes: 8 additions & 6 deletions client/src/components/Modal/SettingModal/SettingModal.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ export const BodyContainer = styled.div`
padding: 0.9375rem 1.875rem 0.9375rem 1.875rem;
`

export const BlockContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
height: max-content;
margin-bottom: 0.9375rem;
`

export const HeaderText = styled.div`
${TYPO.BOLD_M}
margin-bottom: 0.9375rem;
Expand Down Expand Up @@ -92,17 +100,11 @@ export const InputButton = styled.div<ThemeInterface>`
cursor: pointer;
`

export const Gap = styled.div`
width: 100%;
height: 1rem;
`

export const SettingContainer = styled.div`
display: flex;
justify-content: space-between;
width: 100%;
height: 2.25rem;
margin-bottom: 0.9375rem;
`

export const ToggleContainer = styled.div<{ isDarkMode: boolean }>`
Expand Down
198 changes: 151 additions & 47 deletions client/src/components/Modal/SettingModal/SettingModal.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,124 @@
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useRecoilState } from 'recoil'
import * as styles from './SettingModal.styles'
import { ThemeFlag } from '@/types/theme'
import { themeState } from '@/states/theme'
import { userState } from '@/states/user'

interface SettingModalProps {
onConfirm: () => void
}

const SettingModal = ({ onConfirm }: SettingModalProps) => {
const [id, setId] = useState<string>('')
const [password, setPassword] = useState<string>('')
const [currentTheme, setTheme] = useRecoilState(themeState)
const isDarkMode = currentTheme === ThemeFlag.dark
const [user, setUser] = useRecoilState(userState)
const [id, setId] = useState<string>(user.id)
const [nickname, setNickname] = useState<string>(user.nickname)
const [streamKey, setStreamKey] = useState<string>('')

const toggleTheme = () => {
const onToggleContainer = () => {
setTheme(isDarkMode ? ThemeFlag.light : ThemeFlag.dark)
localStorage.setItem('theme', `${currentTheme}`)
}

const onIdInputButton = () => {
if (id.trim() === '') {
alert('올바른 ID를 입력해주세요.')
setId(user.id)

return
} else if (id.trim() === user.id) {
setId(user.id)

return
}

fetch('https://api.gbs-live.site/users/', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ nickname: user.nickname, userId: id.trim() }),
credentials: 'include',
})
.then((res) => {
if (res.ok === true) {
return res.json()
} else {
throw new Error('Save Failed')
}
})
.then((res) => {
const userId = res.userId
const userNickname = res.nickname

alert('ID가 저장되었습니다.')
setUser({ id: userId, nickname: userNickname })
localStorage.setItem('user', JSON.stringify({ id: userId, nickname: userNickname }))
})
.catch((err) => console.error(err))
}

const onNicknameInputButton = () => {
if (nickname.trim() === '') {
alert('올바른 닉네임을 입력해주세요.')
setNickname(user.nickname)

return
} else if (nickname.trim() === user.nickname) {
setNickname(user.nickname)

return
}

fetch('https://api.gbs-live.site/users/', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ nickname: nickname.trim(), userId: user.id }),
credentials: 'include',
})
.then((res) => {
if (res.ok === true) {
return res.json()
} else {
throw new Error('Save Failed')
}
})
.then((res) => {
const userId = res.userId
const userNickname = res.nickname

alert('닉네임이 저장되었습니다.')
setUser({ id: userId, nickname: userNickname })
localStorage.setItem('user', JSON.stringify({ id: userId, nickname: userNickname }))
})
.catch((err) => console.error(err))
}

const onKeyInputButton = () => {
navigator.clipboard.writeText(streamKey).then(() => {
alert('방송 비밀 키가 클립보드에 복사되었습니다.')
})
}

useEffect(() => {
fetch('https://api.gbs-live.site/stream-keys/me/', { method: 'GET', credentials: 'include' })
.then((res) => {
if (res.ok === true) {
return res.json()
} else {
throw new Error('Get Failed')
}
})
.then((res) => {
setStreamKey(res.streamKey)
})
.catch((err) => console.error(err))
}, [])

return (
<styles.Backdrop onClick={onConfirm}>
<styles.ModalContainer>
Expand All @@ -29,49 +129,53 @@ const SettingModal = ({ onConfirm }: SettingModalProps) => {
currentTheme={currentTheme}
>
<styles.BodyContainer>
<styles.HeaderText>마이페이지</styles.HeaderText>
<styles.BodyText>ID</styles.BodyText>
<styles.InputContainer>
<styles.Input
value={id}
onChange={(event) => {
setId(event.target.value)
}}
currentTheme={currentTheme}
/>
<styles.InputButton currentTheme={currentTheme}>저장하기</styles.InputButton>
</styles.InputContainer>
<styles.BodyText>닉네임</styles.BodyText>
<styles.InputContainer>
<styles.Input
value={password}
onChange={(event) => {
setPassword(event.target.value)
}}
currentTheme={currentTheme}
/>
<styles.InputButton currentTheme={currentTheme}>저장하기</styles.InputButton>
</styles.InputContainer>
<styles.BodyText>방송 비밀 키</styles.BodyText>
<styles.InputContainer>
<styles.Input
value={password}
type="password"
onChange={(event) => {
setPassword(event.target.value)
}}
currentTheme={currentTheme}
/>
<styles.InputButton currentTheme={currentTheme}>복사하기</styles.InputButton>
</styles.InputContainer>
<styles.Gap />
<styles.HeaderText>환경설정</styles.HeaderText>
<styles.SettingContainer>
<styles.BodyText>다크모드</styles.BodyText>
<styles.ToggleContainer isDarkMode={isDarkMode} onClick={toggleTheme}>
<styles.ToggleKnob isDarkMode={isDarkMode} />
</styles.ToggleContainer>
</styles.SettingContainer>
{user.id !== '' && (
<styles.BlockContainer>
<styles.HeaderText>마이페이지</styles.HeaderText>
<styles.BodyText>ID</styles.BodyText>
<styles.InputContainer>
<styles.Input
value={id}
onChange={(event) => {
setId(event.target.value)
}}
currentTheme={currentTheme}
/>
<styles.InputButton onClick={onIdInputButton} currentTheme={currentTheme}>
저장하기
</styles.InputButton>
</styles.InputContainer>
<styles.BodyText>닉네임</styles.BodyText>
<styles.InputContainer>
<styles.Input
value={nickname}
onChange={(event) => {
setNickname(event.target.value)
}}
currentTheme={currentTheme}
/>
<styles.InputButton onClick={onNicknameInputButton} currentTheme={currentTheme}>
저장하기
</styles.InputButton>
</styles.InputContainer>
<styles.BodyText>방송 비밀 키</styles.BodyText>
<styles.InputContainer>
<styles.Input value={streamKey} type="password" readOnly={true} currentTheme={currentTheme} />
<styles.InputButton onClick={onKeyInputButton} currentTheme={currentTheme}>
복사하기
</styles.InputButton>
</styles.InputContainer>
</styles.BlockContainer>
)}
<styles.BlockContainer>
<styles.HeaderText>환경설정</styles.HeaderText>
<styles.SettingContainer>
<styles.BodyText>다크모드</styles.BodyText>
<styles.ToggleContainer isDarkMode={isDarkMode} onClick={onToggleContainer}>
<styles.ToggleKnob isDarkMode={isDarkMode} />
</styles.ToggleContainer>
</styles.SettingContainer>
</styles.BlockContainer>
</styles.BodyContainer>
<styles.ButtonContainer currentTheme={currentTheme}>
<styles.Button onClick={onConfirm}>확인</styles.Button>
Expand Down
2 changes: 0 additions & 2 deletions client/src/pages/BroadcastPage/BroadcastPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ const BroadcastPage = () => {
useEffect(() => {
fetchApi('GET', `/streams/${id}`)
socket.current = io('https://api.gbs-live.site', { withCredentials: true })

socket.current.emit('join', { room: id })

socket.current.on('chat', (chatting: ChattingProps) => {
setChattingList((chattingList) => [chatting, ...chattingList])
})
Expand Down

0 comments on commit 2465967

Please sign in to comment.