58. 글 조회수 추가
ChatGPT가 시키는 대로 했습니다.
1. views/WritePost.vue
2. views/PostDetailView.vue
3. views/UserPosts.vue
4. 실행
ChatGPT에게 물었습니다.
uuidv4 is not defined. 해결 방법은?
To resolve the issue of uuidv4 not being defined, you need to install the uuid library, which provides the function to generate UUIDs. Here's how you can do it:
'uuidv4'가 정의되지 않는 문제를 해결하려면 UUID 생성 기능을 제공하는 'uuid' 라이브러리를 설치해야 합니다. 방법은 다음과 같습니다.
1. Install the uuid package:
1. uuid 패키지를 설치하세요:
npm install uuid
2. Import the uuidv4 function in your Vue component:
2. Vue 구성 요소에서 uuidv4 함수를 가져옵니다:
import { v4 as uuidv4 } from 'uuid';
Here’s how you can update the PostDetailView.vue component with the proper import and usage of uuidv4:
uuidv4를 적절하게 가져오고 사용하여 PostDetailView.vue 구성 요소를 업데이트하는 방법은 다음과 같습니다.
Updated PostDetailView.vue
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<div v-if="post">
<h1>{{ post.title }}</h1>
<div>{{ post.userName }} - {{ formatDate(post.createdAt) }}</div>
<div>{{ post.content }}</div>
<div>Views: {{ post.views }}</div>
</div>
</v-container>
</template>
<script>
import { db } from '../firebase';
import firebase from 'firebase/app';
import { auth } from '../firebase';
import { v4 as uuidv4 } from 'uuid'; // Importing uuidv4
export default {
data() {
return {
post: null,
loading: false,
error: null
};
},
async created() {
const postId = this.$route.params.id;
this.loading = true;
try {
const postRef = db.collection('posts').doc(postId);
const postDoc = await postRef.get();
if (postDoc.exists) {
this.post = { id: postDoc.id, ...postDoc.data() };
const today = new Date().toISOString().split('T')[0];
let userId;
if (auth.currentUser) {
userId = auth.currentUser.uid;
} else {
userId = this.getOrCreateAnonymousUserId();
}
const alreadyViewed = this.post.viewedBy.some(view => view.userId === userId && view.date === today);
if (!alreadyViewed) {
await postRef.update({
views: firebase.firestore.FieldValue.increment(1),
viewedBy: firebase.firestore.FieldValue.arrayUnion({ userId, date: today })
});
this.post.views += 1; // Update the local view count
}
} else {
this.error = { message: 'Post not found' };
}
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
},
methods: {
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
},
getOrCreateAnonymousUserId() {
let userId = localStorage.getItem('anonymousUserId');
if (!userId) {
userId = uuidv4(); // Generate a new UUID
localStorage.setItem('anonymousUserId', userId);
}
return userId;
}
}
};
</script>
Summary 요약
1. Install the uuid package:
‘uuid’ 패키지를 설치하세요:
npm install uuid
2. Import the uuidv4 function in your component:
컴포넌트에서 ‘uuidv4’ 함수를 가져옵니다:
import { v4 as uuidv4 } from 'uuid';
3. Use uuidv4 to generate unique identifiers.
uuidv4를 사용하여 고유 식별자를 생성하세요.
This will resolve the uuidv4 is not defined error and allow you to track unique views for both authenticated and unauthenticated users.
이렇게 하면 'uuidv4가 정의되지 않았습니다' 오류가 해결되고 인증된 사용자와 인증되지 않은 사용자 모두에 대한 고유 보기를 추적할 수 있습니다.
Source Code
1. views/WritePost.vue
<!-- src/views/WritePost.vue -->
<template>
<v-container>
<v-form @submit.prevent="submitPost">
<v-text-field v-model="title" label="Title" required></v-text-field>
<v-textarea v-model="content" label="Content" rows="10" required></v-textarea>
<v-btn type="submit" color="primary">Submit</v-btn>
</v-form>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
export default {
data() {
return {
title: '',
content: '',
};
},
methods: {
async submitPost() {
const user = this.$store.state.auth.user;
//const user = auth.currentUser;
console.log("user: ", user);
if (user) {
try {
await db.collection('posts').add({
title: this.title,
content: this.content,
//userId: user.uid,
//userName: user.displayName, // Ensure the user's name is available
userId: user.id,
userName: user.name,
createdAt: new Date(),
views: 0, // Initialize view count
viewedBy: [] // Initialize viewedBy array
});
//this.$router.push('/post-list');
this.$router.push('/');
} catch (error) {
console.error("Error writing document: ", error);
}
} else {
console.error("User not authenticated");
}
},
},
};
</script>
2. views/PostDetailView.vue
<!-- src/viewa/PostDetailView.vue -->
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<v-card v-if="!loading && post">
<v-card-title>{{ post.title }}</v-card-title>
<v-card-text>{{ post.userName }} - {{ formatDate(post.createdAt) }}</v-card-text>
<v-card-text v-html="postContent"></v-card-text>
<v-card-text>Views: {{ post.views }}</v-card-text>
</v-card>
</v-container>
</template>
<script>
import { db } from '../firebase';
import firebase from 'firebase/compat/app';
import sanitizeHtml from 'sanitize-html';
import { v4 as uuidv4 } from 'uuid'; // Importing uuidv4
export default {
data() {
return {
post: null,
postContent: '',
loading: false,
error: null
};
},
async created() {
this.loading = true;
const postId = this.$route.params.id;
try {
const postRef = db.collection('posts').doc(postId);
//const postDoc = await db.collection('posts').doc(postId).get();
const postDoc = await postRef.get();
if (postDoc.exists) {
this.post = postDoc.data();
this.postContent = this.sanitizeContent(this.post.content);
const today = new Date().toISOString().split('T')[0];
let userId;
const user = this.$store.state.auth.user;
if (user) {
//userId = auth.currentUser.uid;
userId = user.id;
} else {
userId = this.getOrCreateAnonymousUserId();
}
const alreadyViewed = this.post.viewedBy.some(view => view.userId === userId && view.date === today);
if (!alreadyViewed) {
await postRef.update({
views: firebase.firestore.FieldValue.increment(1),
viewedBy: firebase.firestore.FieldValue.arrayUnion({ userId, date: today })
});
this.post.views += 1; // Update the local view count
}
} else {
this.error = { message: 'Post not found' };
}
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
},
methods: {
sanitizeContent(content) {
return sanitizeHtml(content.replace(/\n/g, '<br>'), {
allowedTags: ['b', 'i', 'em', 'strong', 'p', 'br'],
allowedAttributes: {}
});
},
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
},
getOrCreateAnonymousUserId() {
let userId = localStorage.getItem('anonymousUserId');
if (!userId) {
userId = uuidv4();
localStorage.setItem('anonymousUserId', userId);
}
return userId;
}
}
};
</script>
3. views/UserPosts.vue
<!-- src/views/UserPosts.vue -->
<template>
<v-container>
<v-alert v-if="error" type="error" dismissible>{{ error.message }}</v-alert>
<v-progress-circular v-if="loading" indeterminate></v-progress-circular>
<v-list v-if="!loading">
<v-list-item v-for="post in posts" :key="post.id" @click="goToPostDetail(post.id)">
<v-list-item-content>
<v-list-item-title>{{ post.title }}</v-list-item-title>
<v-list-item-subtitle>
<div>{{ post.userName }}</div>
<div>{{ formatDate(post.createdAt) }}</div>
<div>Views: {{ post.views }}</div>
</v-list-item-subtitle>
<v-list-item-subtitle>{{ post.content }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</v-list>
</v-container>
</template>
<script>
import { db, auth } from '../firebase';
export default {
data() {
return {
posts: [],
loading: false,
error: null
};
},
async created() {
this.loading = true;
//const user = auth.currentUser;
const user = this.$store.state.auth.user;
if (user) {
try {
//const querySnapshot = await db.collection('posts').where('userId', '==', user.uid).get();
const querySnapshot = await db.collection('posts').where('userId', '==', user.id).get();
this.posts = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
} catch (error) {
this.error = error;
} finally {
this.loading = false;
}
} else {
this.error = { message: 'User not authenticated' };
this.loading = false;
}
},
methods: {
goToPostDetail(postId) {
this.$router.push({ name: 'PostDetailView', params: { id: postId } });
},
formatDate(date) {
if (date && date.toDate) {
return date.toDate().toLocaleString();
}
return '';
}
}
};
</script>
'PWA' 카테고리의 다른 글
ChatGPT와 함께 PWA Blog 개발 - 답글 (0) | 2024.08.23 |
---|---|
ChatGPT와 함께 PWA Blog 개발 - 댓글 (0) | 2024.08.23 |
ChatGPT와 함께 PWA Blog 개발 - 조회수 (0) | 2024.08.22 |
ChatGPT와 함께 PWA Blog 개발 - 리스트에 글쓴이 (0) | 2024.08.21 |
ChatGPT와 함께 PWA Blog 개발 - 글쓴이 (0) | 2024.08.21 |