Skip to content

Commit

Permalink
Merge branch 'main' into css
Browse files Browse the repository at this point in the history
  • Loading branch information
shota973 authored Jun 16, 2024
2 parents f9fd331 + 664c0c3 commit fed1310
Show file tree
Hide file tree
Showing 11 changed files with 320 additions and 66 deletions.
11 changes: 11 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ module.exports = {
},
],
'no-case-declarations': 'off',
'@typescript-eslint/ban-types': [
'error',
{
types: {
'{}': false,
Object: false,
Function: false,
},
extendDefaults: true,
},
],
},
parser: 'vue-eslint-parser',
parserOptions: {
Expand Down
8 changes: 7 additions & 1 deletion src/icons/ReportIcon.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<script setup lang="ts">
withDefaults(defineProps<{ color: string }>(), {
color: '#FF0000',
})
</script>

<template>
<svg
width="20"
Expand All @@ -20,7 +26,7 @@
<g mask="url(#mask0_37_82)">
<path
d="M10 14.1667C10.2361 14.1667 10.434 14.0868 10.5938 13.9271C10.7535 13.7674 10.8333 13.5694 10.8333 13.3333C10.8333 13.0972 10.7535 12.8993 10.5938 12.7396C10.434 12.5799 10.2361 12.5 10 12.5C9.76389 12.5 9.56597 12.5799 9.40625 12.7396C9.24653 12.8993 9.16667 13.0972 9.16667 13.3333C9.16667 13.5694 9.24653 13.7674 9.40625 13.9271C9.56597 14.0868 9.76389 14.1667 10 14.1667ZM9.16667 10.8333H10.8333V5.83333H9.16667V10.8333ZM6.875 17.5L2.5 13.125V6.875L6.875 2.5H13.125L17.5 6.875V13.125L13.125 17.5H6.875ZM7.58333 15.8333H12.4167L15.8333 12.4167V7.58333L12.4167 4.16667H7.58333L4.16667 7.58333V12.4167L7.58333 15.8333Z"
fill="#FF0000"
:fill="color"
/>
</g>
</svg>
Expand Down
8 changes: 7 additions & 1 deletion src/icons/ThumbUpIcon.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<script setup lang="ts">
withDefaults(defineProps<{ color: string }>(), {
color: '#24A005',
})
</script>

<template>
<svg
width="20"
Expand All @@ -20,7 +26,7 @@
<g mask="url(#mask0_37_77)">
<path
d="M15.0001 17.5H5.83341V6.66666L11.6667 0.833328L12.7084 1.87499C12.8056 1.97222 12.8855 2.10416 12.948 2.27083C13.0105 2.43749 13.0417 2.59722 13.0417 2.74999V3.04166L12.1251 6.66666H17.5001C17.9445 6.66666 18.3334 6.83333 18.6667 7.16666C19.0001 7.49999 19.1667 7.88888 19.1667 8.33333V9.99999C19.1667 10.0972 19.1529 10.2014 19.1251 10.3125C19.0973 10.4236 19.0695 10.5278 19.0417 10.625L16.5417 16.5C16.4167 16.7778 16.2084 17.0139 15.9167 17.2083C15.6251 17.4028 15.3195 17.5 15.0001 17.5ZM7.50008 15.8333H15.0001L17.5001 9.99999V8.33333H10.0001L11.1251 3.74999L7.50008 7.37499V15.8333ZM5.83341 6.66666V8.33333H3.33341V15.8333H5.83341V17.5H1.66675V6.66666H5.83341Z"
fill="#24A005"
:fill="color"
/>
</g>
</svg>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/apis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const api = new Apis(
new Configuration({
basePath:
process.env.NODE_ENV === 'production'
? 'https://trap.show/h24s_19_server'
? 'https://h24s-19.trap.show/server'
: 'http://localhost:3000',
}),
)
Expand Down
10 changes: 8 additions & 2 deletions src/pages/CreateRoom.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,15 @@ const submit = async () => {
try {
const resp = await api.apiRoomPost(roomInfo)
const roomId = resp.data.roomId
let query = undefined
if (!isPublic.value) {
query = { password: roomPassword.value, isPrivate: 1 }
}
router.push({
path: `/rooms/${roomId}`,
query: { password: roomPassword.value },
path: `/rooms/${roomId}/enter`,
query,
})
} catch (e) {
console.error(e)
Expand Down
82 changes: 82 additions & 0 deletions src/pages/EnterRoom.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import api, { EnterRoom } from '@/lib/apis'
import router from '@/router'
import { useStoreUser } from '@/stores/user'
const store = useStoreUser()
// 部屋に入る前のページ
// 必須: 名前
// private -> 合言葉の入力欄
// 名前を適切に設定 && 合言葉が正しい -> IndividualRoom へ
// 名前に被り || 合言葉が不正 -> 失敗を表示して再入力へ
const thisRoomId = ref('')
const userNickName = ref('')
const roomPassword = ref('')
const submitError = ref(false)
const userSettingError = ref(false)
const submit = async () => {
const enterInfo: EnterRoom = {
userName: userNickName.value,
password: roomPassword.value,
}
try {
// enterRoom を送る
const resp = await api.apiRoomRoomIdEnterPost(thisRoomId.value, enterInfo)
// ここで resp から userId と userName を持たせて IndividualRoom へ
submitError.value = false
// stores/user に userId と userName を記録して、 /rooms/:id に移動させる
const userId = resp.data.userId
store.setUser(resp.data.userName, userId)
router.push({ path: `/rooms/${thisRoomId.value}` })
} catch (e) {
// 通信エラー or userNameエラー or password エラー
console.error(e)
submitError.value = true
}
}
const isPrivate = computed(() => 'isPrivate' in router.currentRoute.value.query)
onMounted(() => {
const roomId = router.currentRoute.value.params.id
if (typeof roomId == 'string') {
thisRoomId.value = roomId
} else {
console.error('Invalid RoomId type')
}
const queryPassword = router.currentRoute.value.query['password']
if (typeof queryPassword == 'string') {
roomPassword.value = queryPassword
}
})
</script>
<template>
<h1>部屋に入る</h1>
<p>部屋ID: {{ thisRoomId }}</p>
<p>この部屋で使うニックネームを設定してください。</p>
<p>
<label>
ニックネーム
<input v-model="userNickName" />
</label>
</p>
<p v-if="isPrivate">
<label>
合言葉
<input v-model="roomPassword" />
</label>
</p>

<p>
<button @click="submit">参加</button>
</p>
<div v-if="userSettingError">
<p>ニックネームが使用不可能。もしくは間違った合言葉です。</p>
</div>
<div v-if="submitError">
<p>エラーが発生しました。操作をやり直してください。</p>
</div>
</template>
155 changes: 124 additions & 31 deletions src/pages/IndividualRoom.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useIndividualRoom } from '@/stores/individualRoom'
import { Post, useIndividualRoom } from '@/stores/individualRoom'
import ThumbUpIcon from '@/icons/ThumbUpIcon.vue'
import ReportIcon from '@/icons/ReportIcon.vue'
import { useStoreUser } from '@/stores/user'
const router = useRouter()
const roomId = computed(() =>
Expand All @@ -15,6 +16,9 @@ const roomId = computed(() =>
const individualRoomStore = useIndividualRoom()
const posts = computed(() => individualRoomStore.state.posts)
const userStore = useStoreUser()
const userId = computed(() => userStore.$state.userId)
onMounted(async () => {
try {
await individualRoomStore.connect(roomId.value)
Expand All @@ -29,63 +33,118 @@ const postWord = () => {
individualRoomStore.sendPost(postWordInput.value, postReadingInput.value)
}
const goodWord = (wordId: number) => {
const goodWord = (post: Post) => {
// TODO: デバウンス入れて連打時のリクエスト回数減らしたい
individualRoomStore.goodPost(wordId, 1)
individualRoomStore.goodPost(post, 1)
}
const reportWord = (wordId: number) => {
individualRoomStore.reportPost(wordId)
const reportWord = (post: Post) => {
individualRoomStore.reportPost(post)
}
const ranking = computed(() => {
if (individualRoomStore.state.ws === null) {
return []
}
const ranking: { name: string; score: number }[] = []
for (const userName of Object.keys(individualRoomStore.state.userScoreMap)) {
ranking.push({
name: userName,
score: individualRoomStore.state.userScoreMap[userName],
})
}
ranking.sort((a, b) => b.score - a.score)
return ranking
})
</script>

<template>
<div class="container">
<div class="posted-word-container">
<div v-for="post in posts" :key="post.wordId" class="word-card">
<span class="user-name">{{ post.senderName }}</span>
<span class="word">{{ `${post.word} (${post.reading})` }}</span>
<div class="word-footer">
<span>{{ `基礎点: ${post.basicScore}` }}</span>
<div class="icons-container">
<div class="thumb-container">
<ThumbUpIcon @click="() => goodWord(post.wordId)" />
<span>{{ post.additionalScore }}</span>
<div class="post-area-container">
<div class="posted-word-container">
<div v-for="post in posts" :key="post.wordId" class="word-card">
<span class="user-name">{{ post.senderName }}</span>
<span class="word">{{ `${post.word} (${post.reading})` }}</span>
<div class="word-footer">
<span>{{ `基礎点: ${post.basicScore}` }}</span>
<div class="icons-container">
<div class="thumb-container">
<ThumbUpIcon
:class="{ 'icon-disabled': userId === post.senderId }"
:color="userId === post.senderId ? '#a8d89c' : '#24A005'"
@click="() => goodWord(post)"
/>
<span>{{ post.additionalScore }}</span>
</div>
<ReportIcon
:class="{ 'icon-disabled': userId === post.senderId }"
:color="userId === post.senderId ? '#c15353' : '#FF0000'"
@click="() => reportWord(post)"
/>
</div>
<ReportIcon @click="() => reportWord(post.wordId)" />
</div>
</div>
</div>

<div class="input-container">
<div class="input-area">
<label class="input-label">
{{ '単語' }}
<input v-model="postWordInput" type="text" />
</label>
<label class="input-label">
{{ '単語の読み' }}
<input v-model="postReadingInput" type="text" />
</label>
</div>
<button @click="postWord">
{{ '送信' }}
</button>
</div>
</div>

<div class="input-container">
<div class="input-area">
<label class="input-label">
{{ '単語' }}
<input v-model="postWordInput" type="text" />
</label>
<label class="input-label">
{{ '単語の読み' }}
<input v-model="postReadingInput" type="text" />
</label>
<div class="ranking-container">
<div class="ranking-title">{{ 'ランキング' }}</div>
<div class="ranking-list">
<div
v-for="(user, index) in ranking"
:key="user.name"
class="ranking-individual"
>
<div>
<span :style="{ fontWeight: 'bold', marginRight: '16px' }">
{{ `${index + 1}` }}
</span>
<span>{{ user.name }}</span>
</div>
<span>{{ `${user.score}` }}</span>
</div>
</div>
<button @click="postWord">
{{ '送信' }}
</button>
</div>
</div>
</template>

<style scoped>
.container {
max-width: 700px;
display: grid;
grid-auto-flow: column;
grid-template-columns: 1fr 400px;
height: 100%;
width: 100%;
overflow: hidden;
}
.post-area-container {
height: 100%;
width: 100%;
margin: 0 auto;
overflow: hidden;
display: flex;
flex-direction: column;
position: relative;
padding: 0 20px;
margin-right: 10px;
box-sizing: border-box;
}
.posted-word-container {
Expand Down Expand Up @@ -138,6 +197,10 @@ const reportWord = (wordId: number) => {
gap: 4px;
}
.icon-disabled {
cursor: not-allowed;
}
.input-container {
width: 100%;
display: flex;
Expand All @@ -163,4 +226,34 @@ const reportWord = (wordId: number) => {
width: 100%;
font-size: 20px;
}
.ranking-container {
width: 100%;
overflow-y: auto;
padding: 10px;
margin: 10px;
border-left: 2px solid #5b5b5b;
display: flex;
flex-direction: column;
box-sizing: border-box;
gap: 10px;
}
.ranking-title {
font-size: 25px;
font-weight: bold;
}
.ranking-list {
display: flex;
flex-direction: column;
gap: 4px;
}
.ranking-individual {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 20px;
}
</style>
Loading

0 comments on commit fed1310

Please sign in to comment.