Skip to content

Commit 1d0420f

Browse files
authored
Merge pull request #14 from 2024-Iris/repository
사용자 이메일 업데이트, 알림 설정, 회원 탈퇴 구현
2 parents 9763b03 + fecb982 commit 1d0420f

File tree

12 files changed

+362
-75
lines changed

12 files changed

+362
-75
lines changed

src/App.vue

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<header v-if="!$route.meta.hideHeader" class="bg-white">
33
<nav aria-label="Global" class="flex w-full items-center justify-between py-4 lg:px-8 bg-gray-50">
44
<div class="flex items-center lg:flex-1">
5-
<router-link to="/" class="flex items-center">
5+
<router-link class="flex items-center" to="/">
66
<img alt="issuefy logo" class="h-16 w-auto" src="./assets/issuefy-removebg_logo.png"/>
77
<div v-if="$route.meta.showBreadcrumbs" class="ml-4 flex items-center space-x-2">
88
<router-link :to="`/${$route.params.org}`" class="text-sm font-medium text-gray-900 hover:text-blue-600">
@@ -22,7 +22,7 @@
2222
</div>
2323
<div v-if="isLoggedIn" class="hidden lg:flex lg:items-center lg:gap-x-6">
2424
<div class="relative">
25-
<button @click="toggleNotifications" class="relative">
25+
<button class="relative" @click="toggleNotifications">
2626
<font-awesome-icon icon="bell" style="color: #B197FC;"/>
2727
<span v-if="unreadCount > 0"
2828
class="absolute -top-1 -right-1 bg-red-600 text-white text-xs rounded-full px-1">
@@ -48,22 +48,22 @@
4848
</div>
4949
<div class="flex justify-between items-center">
5050
<span class="text-xs text-gray-500">{{ notification.formattedTime }}</span>
51-
<button v-if="!notification.read" @click="markAsRead(notification.userNotificationId)"
52-
class="text-xs text-purple-500 hover:text-purple-700">
51+
<button v-if="!notification.read" class="text-xs text-purple-500 hover:text-purple-700"
52+
@click="markAsRead(notification.userNotificationId)">
5353
읽음
5454
</button>
5555
</div>
5656
</div>
5757
</div>
5858
<div v-if="notifications.length > visibleNotifications.length" class="p-2 text-center">
59-
<button @click.stop="loadMoreNotifications" class="text-purple-500 hover:text-purple-700">더 보기</button>
59+
<button class="text-purple-500 hover:text-purple-700" @click.stop="loadMoreNotifications">더 보기</button>
6060
</div>
6161
</div>
6262
<div v-else class="p-4 text-gray-500">
6363
알림이 없습니다.
6464
</div>
6565
<div v-if="hasUnreadNotifications" class="p-2 border-t border-gray-200">
66-
<button @click="markAllAsRead" class="w-full text-center text-purple-500 hover:text-purple-700">모두 읽음
66+
<button class="w-full text-center text-purple-500 hover:text-purple-700" @click="markAllAsRead">모두 읽음
6767
</button>
6868
</div>
6969
</div>
@@ -74,8 +74,8 @@
7474
<div v-if="isLoggedIn" class="mx-5"></div>
7575
<div v-if="isLoggedIn" class="flex items-center gap-x-4">
7676
<div class="flex items-center space-x-2">
77-
<img :src="avatarURL" class="w-10 h-10 rounded-full" alt="User Avatar">
78-
<router-link to="/settings" class="text-sm font-semibold leading-6 text-blue-600 hover:underline">
77+
<img :src="avatarURL" alt="User Avatar" class="w-10 h-10 rounded-full">
78+
<router-link class="text-sm font-semibold leading-6 text-blue-600 hover:underline" to="/settings">
7979
{{ userName }}
8080
</router-link>
8181
</div>
@@ -175,13 +175,13 @@ export default {
175175
const markNotificationsAsRead = async (userNotificationIds) => {
176176
try {
177177
const response = await axios.patch(
178-
`${process.env.VUE_APP_API_URL}/notifications`,
179-
{ userNotificationIds },
180-
{
181-
headers: {
182-
'Authorization': `Bearer ${authStore.accessToken}`
178+
`${process.env.VUE_APP_API_URL}/notifications`,
179+
{userNotificationIds},
180+
{
181+
headers: {
182+
'Authorization': `Bearer ${authStore.accessToken}`
183+
}
183184
}
184-
}
185185
);
186186
187187
if (response.status === 200) {
@@ -204,8 +204,8 @@ export default {
204204
205205
const markAllAsRead = async () => {
206206
const unreadNotificationIds = notifications.value
207-
.filter(n => !n.read)
208-
.map(n => n.userNotificationId);
207+
.filter(n => !n.read)
208+
.map(n => n.userNotificationId);
209209
if (unreadNotificationIds.length > 0) {
210210
await markNotificationsAsRead(unreadNotificationIds);
211211
}

src/components/ExpiredPage.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<p class="text-lg mb-8">다시 로그인해주세요.</p>
88
</div>
99
<div class="text-left">
10-
<router-link to="/login" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm">
10+
<router-link class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" to="/login">
1111
로그인
1212
</router-link>
1313
</div>

src/components/GithubAuth.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup>
2-
import { onMounted, nextTick } from 'vue';
3-
import { useRouter, useRoute } from 'vue-router';
4-
import { useAuthStore } from '@/store/pinia';
2+
import {nextTick, onMounted} from 'vue';
3+
import {useRoute, useRouter} from 'vue-router';
4+
import {useAuthStore} from '@/store/pinia';
55
import axios from 'axios';
66
77
const router = useRouter();
@@ -12,11 +12,11 @@ const authStore = useAuthStore();
1212
async function fetchJWT(code) {
1313
try {
1414
const response = await axios.get(`${process.env.VUE_APP_API_URL}/login`, {
15-
params: { code }
15+
params: {code}
1616
});
17-
const { jwt, userName, avatarURL } = response.data;
18-
const { accessToken, refreshToken } = jwt;
19-
return { accessToken, refreshToken, userName, avatarURL };
17+
const {jwt, userName, avatarURL} = response.data;
18+
const {accessToken, refreshToken} = jwt;
19+
return {accessToken, refreshToken, userName, avatarURL};
2020
} catch (error) {
2121
console.error('Error fetching JWT:', error);
2222
return null;

src/components/IssueDetailPage.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
<div class="flex justify-between items-center">
66
<h1 class="text-lg leading-6 font-medium text-gray-900">{{ issue.title }}</h1>
77
<div>
8-
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full"
9-
:class="{'bg-green-100 text-green-800': issue.status === 'open', 'bg-red-100 text-red-800': issue.status === 'closed'}">
8+
<span
9+
:class="{'bg-green-100 text-green-800': issue.status === 'open', 'bg-red-100 text-red-800': issue.status === 'closed'}"
10+
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
1011
{{ issue.status }}
1112
</span>
1213
</div>
@@ -21,8 +22,8 @@
2122
</div>
2223
<div v-if="issue.labels.length > 0" class="px-4 py-4 sm:px-6">
2324
<span v-for="label in issue.labels" :key="label"
24-
class="inline-flex items-center px-3 py-0.5 rounded-full text-sm font-medium leading-5 mr-2"
25-
:style="{ backgroundColor: getColorForLabel(label), color: getTextColorForLabel(label) }">
25+
:style="{ backgroundColor: getColorForLabel(label), color: getTextColorForLabel(label) }"
26+
class="inline-flex items-center px-3 py-0.5 rounded-full text-sm font-medium leading-5 mr-2">
2627
{{ label }}
2728
</span>
2829
</div>

src/components/IssuePage.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<div v-for="issue in filteredIssues" :key="issue.id"
1212
class="issue bg-white border-b border-gray-200 py-4 px-6 flex justify-between items-center hover:bg-gray-100">
1313
<div class="w-1/3 text-left flex items-center">
14-
<button @click="toggleStar(issue.id)" class="text-yellow-500 mr-2">
14+
<button class="text-yellow-500 mr-2" @click="toggleStar(issue.id)">
1515
{{ issue.star ? '★' : '☆' }}
1616
</button>
1717
<router-link :to="`/${org}/${repository}/issues/` + issue.id"
@@ -28,8 +28,8 @@
2828
</div>
2929
</div>
3030
<div class="w-1/3 text-center">
31-
<span class="status text-sm font-semibold"
32-
:class="{'text-green-500': issue.status === 'open', 'text-red-500': issue.status === 'closed'}">{{
31+
<span :class="{'text-green-500': issue.status === 'open', 'text-red-500': issue.status === 'closed'}"
32+
class="status text-sm font-semibold">{{
3333
issue.status
3434
}}</span>
3535
<p class="text-sm text-gray-600">{{ issue.updatedAt }}</p>

src/components/LoginPage.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ const clientId = process.env.VUE_APP_GITHUB_CLIENT_ID;
33
const redirectUri = encodeURIComponent(`${process.env.VUE_APP_CALLBACK_URL}`);
44
55
function handleGitHubLogin() {
6-
// GitHub 로그인 페이지로 리디렉션
76
window.location.href = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}`;
87
}
98

src/components/LogoutPage.vue

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,31 @@
11
<script setup>
2-
32
import {useAuthStore} from "@/store/pinia";
43
import {useRouter} from "vue-router";
4+
import axios from "axios";
5+
import {onMounted} from 'vue';
56
67
const authStore = useAuthStore()
78
const router = useRouter()
89
9-
authStore.clearCredentials()
10-
router.push('/login')
10+
async function performLogout() {
11+
try {
12+
const accessToken = authStore.accessToken;
13+
await axios.post(`${process.env.VUE_APP_API_URL}/logout`, {}, {
14+
headers: {
15+
Authorization: `Bearer ${accessToken}`
16+
}
17+
});
18+
19+
await authStore.clearCredentials()
20+
await router.push('/login')
21+
} catch (error) {
22+
console.error('Logout failed:', error);
23+
}
24+
}
25+
26+
onMounted(() => {
27+
performLogout();
28+
})
1129
</script>
1230

1331
<template>

src/components/RepositoryNotificationPage.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div v-if="show" class="notification" :class="type">
2+
<div v-if="show" :class="type" class="notification">
33
<div class="notification-content">
44
<font-awesome-icon v-if="type === 'success'" icon="check" style="color: #63E6BE;"/>
55
<font-awesome-icon v-else icon="circle-exclamation"/>

src/components/RepositoryPage.vue

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,43 @@
22
<div class="container mx-auto mt-6 max-w-7xl font-sans">
33
<div class="text-black py-4 px-6 flex justify-between items-center font-bold">
44
<div v-if="!hideListName">
5-
<h1 class="text-base text-left font-bold">리포지토리 목록</h1>
5+
<h1 class="text-lg text-left font-bold">리포지토리 목록</h1>
66
</div>
77
<div v-if="!hideAddBox" class="flex items-center space-x-4 w-2/3 justify-end">
88
<div v-if="adding" v-click-outside="cancelAdding" class="flex items-center space-x-2">
99
<input
10-
v-model="newRepositoryUrl"
11-
@keyup.enter="addRepository"
12-
type="text"
1310
id="newRepositoryUrl"
11+
v-model="newRepositoryUrl"
12+
class="input-full-width font-thin px-3 py-1 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-blue-200"
1413
name="newRepositoryUrl"
1514
placeholder="Enter Repository URL"
16-
class="input-full-width font-thin px-3 py-1 border border-gray-300 rounded-md focus:outline-none focus:ring focus:ring-blue-200"
15+
type="text"
16+
@keyup.enter="addRepository"
1717
/>
18-
<button @click="addRepository"
19-
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm">
18+
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm"
19+
@click="addRepository">
2020
추가
2121
</button>
22-
<button @click="cancelAdding"
23-
class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded text-sm">
22+
<button class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded text-sm"
23+
@click="cancelAdding">
2424
취소
2525
</button>
2626
</div>
27-
<button v-if="!adding" @click="startAdding"
28-
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm">
27+
<button v-if="!adding" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm"
28+
@click="startAdding">
2929
리포지토리 추가
3030
</button>
31-
<button v-if="hasSelectedRepositories" @click="deleteSelectedRepositories"
32-
class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded text-sm">
31+
<button v-if="hasSelectedRepositories"
32+
class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded text-sm"
33+
@click="deleteSelectedRepositories">
3334
리포지토리 삭제
3435
</button>
3536
</div>
3637
</div>
3738

3839
<div class="repository-header bg-gray-100 py-4 px-6 flex justify-between items-center font-semibold">
3940
<div class="w-1/12 text-left">
40-
<input type="checkbox" v-model="allSelected" @change="toggleSelectAll">
41+
<input v-model="allSelected" type="checkbox" @change="toggleSelectAll">
4142
</div>
4243

4344
<div class="w-1/3 text-left text-base">조직 이름</div>
@@ -49,10 +50,10 @@
4950
<div v-for="repository in org.org.repositories" :key="repository.id"
5051
class="repository bg-white border-b border-gray-200 py-4 px-6 flex justify-between items-center hover:bg-gray-100">
5152
<div class="w-1/12 text-left">
52-
<input type="checkbox" v-model="repository.selected">
53+
<input v-model="repository.selected" type="checkbox">
5354
</div>
5455
<div class="w-1/3 text-left flex items-center">
55-
<button @click="toggleStar(repository.id)" class="text-yellow-500 mr-2">
56+
<button class="text-yellow-500 mr-2" @click="toggleStar(repository.id)">
5657
{{ repository.star ? '★' : '☆' }}
5758
</button>
5859
<span class="org text-base font-bold mr-3">{{ org.org.name }}</span>
@@ -69,7 +70,7 @@
6970
</div>
7071
</div>
7172

72-
<Notification :show="showNotification" :type="notificationType" :message="notificationMessage"/>
73+
<Notification :message="notificationMessage" :show="showNotification" :type="notificationType"/>
7374
</div>
7475
</template>
7576

0 commit comments

Comments
 (0)