Vue로 PWA 개발

30. mylog 수정, 내 마이로그 보기 구현

그랜파 개발자 2024. 10. 25. 14:46

1. 마이로그 수정

마이로그 상세 보기에서 마이로그를 수정할 수 있습니다. 마이로그의 수정은 쓴 사람만이 수정할 수 있으므로 로그인한 사용자의 id와 마이로그의 usrId가 같은 마이로그는 ‘수정’ 버튼이 나타납니다. 수정 버튼을 누르면 마이로그 수정화면이 나타나고 여기에서 마이로그를 수정할 수 있습니다. 마이로그를 수정하면 이미 로드한 마이로그의 정보도 같이 수정해야 합니다.

src/views/MyLogView.vue

<!-- src/views/MyLogView.vue -->
<template>
  <v-container>
    <v-row justify="center">
      <v-col cols="12" md="8">
        <v-card v-if="mylog">
          <v-card-title>{{ mylog.title }}</v-card-title>
          <v-card-subtitle>
            {{ mylog.userName }} Posted on: {{ mylog.createdAt.toDate().toLocaleString() }} ({{ mylog.views }})
          </v-card-subtitle>
          <v-card-text>
            <!-- eslint-disable -->
            <v-card-text v-html="content"></v-card-text>
            <!-- eslint-enable -->
          </v-card-text>

          <v-card-actions v-if="isAuthor">
            <!-- 게시물 수정 버튼 -->
            <v-btn @click="goToEditMylog()"> 수정 &nbsp; <v-icon>mdi-pencil</v-icon></v-btn>
          </v-card-actions>  

        </v-card>
        <v-alert v-else type="error" dismissible @input="resetErrorMsg" class="my-alert">
          Mylog not found. Please check the link and try again.
        </v-alert>
        <!-- <v-alert v-if="error" type="error" dismissible @input="resetErrorMsg" class="my-alert">{{ error }}</v-alert> -->
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import { mapActions, mapGetters } from "vuex";
import sanitizeHtml from 'sanitize-html';

export default {
  data() {
    return {
      content: ''
    };
  },
  async created() {
    // 마이로그 가죠오기
    const mylogId = this.$route.params.id; // Get the article ID from the route parameters
    await this.fetchMylog(mylogId); // 마이로그 아이디로 마이로그를 가져온다.
    this.content = this.sanitizeContent(this.mylog.content);  // 내용에 포한된 html을 안전한 html로 변경한다.

    // 조회수를 증가한다.
    // 같은 회원은 몇번을 방문해도 하루 1회, 비회원도 조회수 증가시킴
    const userId = this.$store.state.auth.user ? this.$store.state.auth.user.id : null; // 로그인 여부 확인  
    await this.updateViewCount(mylogId, userId); // 조회수 업데이트 및 기록
  },  
  computed: {
    ...mapGetters('mylogs',['mylog']),   // 'mylog' mylogs store의 mylog getter로서 현재 선택된 마이로그를 돌려준다. 
    // 작성자와 로그인한 사용자 비교
    isAuthor() {
      return this.$store.state.auth.user && this.$store.state.auth.user.id === this.mylog.userId;
    },
  },
  methods: { 
    // 'fetchMylog' mylogs의 action 함수로 마이로그를 firestore 에서 읽어온다. 
    ...mapActions('mylogs', ['fetchMylog', 'resetError', 'updateViewCount']),

    // content를 안전한 html로 바꿔준다.
    sanitizeContent(content) {
      return sanitizeHtml(content.replace(/\n/g, '<br>'), {
        allowedTags: ['b', 'i', 'em', 'strong', 'p', 'br'],
        allowedAttributes: {}
      });
    },
   // 수정화면으로 이동, mylogId, mylog를 파라미터로 보낸다. 
    goToEditMylog() {
      this.$router.push({ name: 'EditMyLogView', params: { mylogId: this.$route.params.id, mylog: this.mylog } });
    },
    resetErrorMsg() {
      this.resetError();
    }
  }
};
</script>

src/router/index.js

{
  path: '/mylog/edit/:mylog',
  name: 'EditMyLogView',
  component: EditMyLogView,
  props: true,   // props를 받는다.
},

src/views/EditMyLogView.vue

<!-- src/views/EditMyLogView.vue -->
<template>
  <div>
    <h3>마이로그 수정</h3>
    <v-form ref="form" v-model="valid">
      <v-text-field label="Title" v-model="editedMylog.title" :rules="[v => !!v || 'Title is required']"></v-text-field>
      <v-textarea label="Content" rows="20" v-model="editedMylog.content" :rules="[v => !!v || 'Content is required']"></v-textarea>
      <v-btn :disabled="!valid" @click="submitMylog"> 수정 </v-btn>
    </v-form>
  </div>
</template>

<script>
import { mapActions, mapGetters } from "vuex";

export default {
  props: {
    mylogId: {
      type: String,
      required: true,
    },
    mylog: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      editedMylog: { mylogId: this.mylogId, ...this.mylog }, // 초기값을 props로 전달된 post로 설정
      valid: false, // 유효성 검사
    };
  },
  methods: {
    ...mapActions('mylogs', ['updateMylog']),
    async submitMylog() {
      if (this.$refs.form.validate()) {
        // Vuex 액션 호출하여 게시물 수정 
        await this.updateMylog({mylogId: this.mylogId, updatedData: this.editedMylog});        
        this.$router.push({ name: "MyLogView", params: { id: this.mylogId } });
      }
    },
  },
};
</script>

2. 내 마이로그 보기

내 마이로그를 모아볼 수 있습니다.

src/views/MyMyLogsView.vue

Copy<!-- src/views/MyMyLogsView.vue -->
<template>
  <div>
    <h3>{{ getMylogName }}</h3>
    <v-list v-if="userMylogs.length > 0">
      <v-list-item v-for="mylog in userMylogs" :key="mylog.id" @click="goToMylogDetail(mylog.id)">
        <v-list-item-content>
          <v-list-item-title>{{ mylog.title }}</v-list-item-title>
          <v-list-item-subtitle>{{ mylog.createdAt.toDate().toLocaleDateString() }}</v-list-item-subtitle>
          <v-list-item-subtitle>{{ mylog.content }}</v-list-item-subtitle>

        </v-list-item-content>
      </v-list-item>
    </v-list>
    <p v-else>You haven't written any posts yet.</p>
  </div>
</template>

<script>
import { mapActions, mapGetters } from "vuex";

export default {

  computed: {
    ...mapGetters('mylogs',['userMylogs']),
    getMylogName() {
      return this.$store.state.auth.user.mylogname;
    }
  },
  methods: {
    ...mapActions('mylogs', ['fetchUserMylogs']),
    goToMylogDetail(mylogId) {
      this.$router.push({ name: 'MyLogView', params: { id: mylogId } });
    }
  },
  mounted() {
    const userId = this.$store.state.auth.user.id;
    this.fetchUserMylogs(userId); // 본인 작성 글 가져오기
  },
};
</script>

'Vue로 PWA 개발' 카테고리의 다른 글

32. mylog 댓글 쓰기 구현  (0) 2024.10.26
31. mylog 댓글 쓰기  (0) 2024.10.26
29. mylog 모아보기  (0) 2024.10.25
28. mylog 수정  (0) 2024.10.25
27. mylog 기본 워크플로우 완성  (0) 2024.10.24