From f7699ae18c325b260235ee2d1529a03e578b1c9e Mon Sep 17 00:00:00 2001
From: Aldino Kemal <aldinokemal2104@gmail.com>
Date: Mon, 11 Mar 2024 19:03:40 +0700
Subject: [PATCH] feat: take out all message and send audio

---
 src/views/components/MessageReact.js  | 116 +++++++++
 src/views/components/MessageRevoke.js | 107 ++++++++
 src/views/components/MessageUpdate.js |  74 +++---
 src/views/components/SendAudio.js     | 111 +++++++++
 src/views/components/SendPoll.js      |  82 +++---
 src/views/index.html                  | 342 +-------------------------
 6 files changed, 421 insertions(+), 411 deletions(-)
 create mode 100644 src/views/components/MessageReact.js
 create mode 100644 src/views/components/MessageRevoke.js
 create mode 100644 src/views/components/SendAudio.js

diff --git a/src/views/components/MessageReact.js b/src/views/components/MessageReact.js
new file mode 100644
index 0000000..ffc8ba5
--- /dev/null
+++ b/src/views/components/MessageReact.js
@@ -0,0 +1,116 @@
+export default {
+    name: 'ReactMessage',
+    data() {
+        return {
+            type: 'user',
+            phone: '',
+            message_id: '',
+            emoji: '',
+            loading: false,
+        }
+    },
+    computed: {
+        phone_id() {
+            return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
+        }
+    },
+    methods: {
+        messageModal() {
+            $('#modalMessageReaction').modal({
+                onApprove: function () {
+                    return false;
+                }
+            }).modal('show');
+        },
+        async messageProcess() {
+            try {
+                let response = await this.messageApi()
+                showSuccessInfo(response)
+                $('#modalMessageReaction').modal('hide');
+            } catch (err) {
+                showErrorInfo(err)
+            }
+        },
+        messageApi() {
+            return new Promise(async (resolve, reject) => {
+                try {
+                    this.loading = true;
+                    let payload = new FormData();
+                    payload.append("phone", this.phone_id)
+                    payload.append("emoji", this.emoji)
+                    let response = await http.post(`/message/${this.message_id}/reaction`, payload)
+                    this.messageReset();
+                    resolve(response.data.message)
+                } catch (error) {
+                    if (error.response) {
+                        reject(error.response.data.message)
+                    } else {
+                        reject(error.message)
+                    }
+                } finally {
+                    this.loading = false;
+                }
+            })
+        },
+        messageReset() {
+            this.phone = '';
+            this.message_id = '';
+            this.emoji = '';
+            this.type = 'user';
+        },
+    },
+    template: `
+    <div class="red card" @click="messageModal()" style="cursor: pointer">
+        <div class="content">
+            <a class="ui red right ribbon label">Message</a>
+            <div class="header">React Message</div>
+            <div class="description">
+                 any message in private or group chat
+            </div>
+        </div>
+    </div>
+    
+    
+    <!--  Modal MessageReaction  -->
+    <div class="ui small modal" id="modalMessageReaction">
+        <i class="close icon"></i>
+        <div class="header">
+             React Message
+        </div>
+        <div class="content">
+            <form class="ui form">
+                <div class="field">
+                    <label>Type</label>
+                    <select name="type" v-model="type" aria-label="type">
+                        <option value="group">Group Message</option>
+                        <option value="user">Private Message</option>
+                    </select>
+                </div>
+                <div class="field">
+                    <label>Phone / Group ID</label>
+                    <input v-model="phone" type="text" placeholder="6289..."
+                           aria-label="phone">
+                    <input :value="phone_id" disabled aria-label="whatsapp_id">
+                </div>
+                <div class="field">
+                    <label>Message ID</label>
+                    <input v-model="message_id" type="text" placeholder="Please enter your message id"
+                           aria-label="message id">
+                </div>
+                <div class="field">
+                    <label>Emoji</label>
+                    <input v-model="emoji" type="text" placeholder="Please enter emoji"
+                           aria-label="message id">
+                </div>
+            </form>
+        </div>
+        <div class="actions">
+            <div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
+                 @click="messageProcess">
+                Send
+                <i class="send icon"></i>
+            </div>
+        </div>
+    </div>
+    `
+}
\ No newline at end of file
diff --git a/src/views/components/MessageRevoke.js b/src/views/components/MessageRevoke.js
new file mode 100644
index 0000000..a0c9f68
--- /dev/null
+++ b/src/views/components/MessageRevoke.js
@@ -0,0 +1,107 @@
+export default {
+    name: 'Message',
+    data() {
+        return {
+            type: 'user',
+            phone: '',
+            message_id: '',
+            loading: false,
+        }
+    },
+    computed: {
+        phone_id() {
+            return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
+        }
+    },
+    methods: {
+        messageModal() {
+            $('#modalMessageRevoke').modal({
+                onApprove: function () {
+                    return false;
+                }
+            }).modal('show');
+        },
+        async messageProcess() {
+            try {
+                let response = await this.messageApi()
+                showSuccessInfo(response)
+                $('#modalMessageRevoke').modal('hide');
+            } catch (err) {
+                showErrorInfo(err)
+            }
+        },
+        messageApi() {
+            return new Promise(async (resolve, reject) => {
+                try {
+                    this.loading = true;
+                    let payload = new FormData();
+                    payload.append("phone", this.phone_id)
+                    let response = await http.post(`/message/${this.message_id}/revoke`, payload)
+                    this.messageReset();
+                    resolve(response.data.message)
+                } catch (error) {
+                    if (error.response) {
+                        reject(error.response.data.message)
+                    } else {
+                        reject(error.message)
+                    }
+                } finally {
+                    this.loading = false;
+                }
+            })
+        },
+        messageReset() {
+            this.phone = '';
+            this.message_id = '';
+            this.type = 'user';
+        },
+    },
+    template:`
+    <div class="red card" @click="messageModal()" style="cursor: pointer">
+        <div class="content">
+            <a class="ui red right ribbon label">Message</a>
+            <div class="header">Revoke Message</div>
+            <div class="description">
+                 any message in private or group chat
+            </div>
+        </div>
+    </div>
+    
+    <!--  Modal MessageRevoke  -->
+    <div class="ui small modal" id="modalMessageRevoke">
+        <i class="close icon"></i>
+        <div class="header">
+             Revoke Message
+        </div>
+        <div class="content">
+            <form class="ui form">
+                <div class="field">
+                    <label>Type</label>
+                    <select name="type" v-model="type" aria-label="type">
+                        <option value="group">Group Message</option>
+                        <option value="user">Private Message</option>
+                    </select>
+                </div>
+                <div class="field">
+                    <label>Phone / Group ID</label>
+                    <input v-model="phone" type="text" placeholder="6289..."
+                           aria-label="phone">
+                    <input :value="phone_id" disabled aria-label="whatsapp_id">
+                </div>
+                <div class="field">
+                    <label> Message ID</label>
+                    <input v-model="message_id" type="text" placeholder="Please enter your message id"
+                           aria-label="message id">
+                </div>
+            </form>
+        </div>
+        <div class="actions">
+            <div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
+                 @click="messageProcess">
+                Send
+                <i class="send icon"></i>
+            </div>
+        </div>
+    </div>
+    `
+}
\ No newline at end of file
diff --git a/src/views/components/MessageUpdate.js b/src/views/components/MessageUpdate.js
index 6ca4644..4c8ca5e 100644
--- a/src/views/components/MessageUpdate.js
+++ b/src/views/components/MessageUpdate.js
@@ -1,48 +1,48 @@
 export default {
-    name: 'Update Message',
+    name: 'UpdateMessage',
     data() {
         return {
-            update_type: 'user',
-            update_phone: '',
-            update_message_id: '',
-            update_new_message: '',
-            update_loading: false,
+            type: 'user',
+            phone: '',
+            message_id: '',
+            new_message: '',
+            loading: false,
         }
     },
     computed: {
-        update_phone_id() {
-            return this.update_type === 'user' ? `${this.update_phone}@${window.TYPEUSER}` : `${this.update_phone}@${window.TYPEGROUP}`
+        phone_id() {
+            return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
         }
     },
     methods: {
-        messageEditModal() {
-            $('#modalMessageEdit').modal({
+        messageModal() {
+            $('#modalMessageUpdate').modal({
                 onApprove: function () {
                     return false;
                 }
             }).modal('show');
         },
-        async messageEditProcess() {
+        async messageProcess() {
             try {
-                let response = await this.messageEditApi()
+                let response = await this.messageApi()
                 showSuccessInfo(response)
-                $('#modalMessageEdit').modal('hide');
+                $('#modalMessageUpdate').modal('hide');
             } catch (err) {
                 showErrorInfo(err)
             }
         },
-        messageEditApi() {
+        messageApi() {
             return new Promise(async (resolve, reject) => {
                 try {
-                    this.update_loading = true;
+                    this.loading = true;
 
                     const payload = {
-                        phone: this.update_phone_id,
-                        message: this.update_new_message
+                        phone: this.phone_id,
+                        message: this.new_message
                     }
 
-                    let response = await http.post(`/message/${this.update_message_id}/update`, payload)
-                    this.messageEditReset();
+                    let response = await http.post(`/message/${this.message_id}/update`, payload)
+                    this.messageReset();
                     resolve(response.data.message)
                 } catch (error) {
                     if (error.response) {
@@ -51,31 +51,31 @@ export default {
                         reject(error.message)
                     }
                 } finally {
-                    this.update_loading = false;
+                    this.loading = false;
                 }
             })
         },
-        messageEditReset() {
-            this.update_type = 'user';
-            this.update_phone = '';
-            this.update_message_id = '';
-            this.update_new_message = '';
-            this.update_loading = false;
+        messageReset() {
+            this.type = 'user';
+            this.phone = '';
+            this.message_id = '';
+            this.new_message = '';
+            this.loading = false;
         },
     },
     template: `
-    <div class="red card" @click="messageEditModal()" style="cursor: pointer">
+    <div class="red card" @click="messageModal()" style="cursor: pointer">
         <div class="content">
             <a class="ui red right ribbon label">Message</a>
-            <div class="header">Edit Message</div>
+            <div class="header">Update Message</div>
             <div class="description">
                 Update your sent message
             </div>
         </div>
     </div>
         
-        <!--  Modal MessageEdit  -->
-    <div class="ui small modal" id="modalMessageEdit">
+        <!--  Modal MessageUpdate  -->
+    <div class="ui small modal" id="modalMessageUpdate">
         <i class="close icon"></i>
         <div class="header">
             Update Message
@@ -84,32 +84,32 @@ export default {
             <form class="ui form">
                 <div class="field">
                     <label>Type</label>
-                    <select name="update_type" v-model="update_type" aria-label="type">
+                    <select name="type" v-model="type" aria-label="type">
                         <option value="group">Group Message</option>
                         <option value="user">Private Message</option>
                     </select>
                 </div>
                 <div class="field">
                     <label>Phone / Group ID</label>
-                    <input v-model="update_phone" type="text" placeholder="6289..."
+                    <input v-model="phone" type="text" placeholder="6289..."
                            aria-label="phone">
-                    <input :value="update_phone_id" disabled aria-label="whatsapp_id">
+                    <input :value="phone_id" disabled aria-label="whatsapp_id">
                 </div>
                 <div class="field">
                     <label>Message ID</label>
-                    <input v-model="update_message_id" type="text" placeholder="Please enter your message id"
+                    <input v-model="message_id" type="text" placeholder="Please enter your message id"
                            aria-label="message id">
                 </div>
                 <div class="field">
                     <label>New Message</label>
-                    <textarea v-model="update_new_message" type="text" placeholder="Hello this is your new message text, you can edit before 15 minutes after sent."
+                    <textarea v-model="new_message" type="text" placeholder="Hello this is your new message text, you can edit before 15 minutes after sent."
                               aria-label="message"></textarea>
                 </div>
             </form>
         </div>
         <div class="actions">
-            <div class="ui approve positive right labeled icon button" :class="{'loading': this.update_loading}"
-                 @click="messageEditProcess">
+            <div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
+                 @click="messageProcess">
                 Update
                 <i class="send icon"></i>
             </div>
diff --git a/src/views/components/SendAudio.js b/src/views/components/SendAudio.js
new file mode 100644
index 0000000..714a85d
--- /dev/null
+++ b/src/views/components/SendAudio.js
@@ -0,0 +1,111 @@
+export default {
+    name: 'Send',
+    data() {
+        return {
+            phone: '',
+            type: 'user',
+            loading: false,
+        }
+    },
+    computed: {
+        phone_id() {
+            return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
+        }
+    },
+    methods: {
+        sendModal() {
+            $('#modalAudioSend').modal({
+                onApprove: function () {
+                    return false;
+                }
+            }).modal('show');
+        },
+        async sendProcess() {
+            try {
+                let response = await this.sendApi()
+                showSuccessInfo(response)
+                $('#modalAudioSend').modal('hide');
+            } catch (err) {
+                showErrorInfo(err)
+            }
+        },
+        sendApi() {
+            return new Promise(async (resolve, reject) => {
+                try {
+                    this.loading = true;
+                    let payload = new FormData();
+                    payload.append("phone", this.phone_id)
+                    payload.append("audio", $("#file")[0].files[0])
+                    let response = await http.post(`/send/audio`, payload)
+                    this.sendReset();
+                    resolve(response.data.message)
+                } catch (error) {
+                    if (error.response) {
+                        reject(error.response.data.message)
+                    } else {
+                        reject(error.message)
+                    }
+                } finally {
+                    this.loading = false;
+                }
+            })
+        },
+        sendReset() {
+            this.phone = '';
+            this.type = 'user';
+            $("#file").val('');
+        },
+    },
+    template:`
+    <div class="blue card" @click="sendModal()" style="cursor: pointer">
+        <div class="content">
+            <a class="ui blue right ribbon label">Send</a>
+            <div class="header">Send Audio</div>
+            <div class="description">
+                Send audio to user or group
+            </div>
+        </div>
+    </div>
+    
+    <!--  Modal SendAudio  -->
+    <div class="ui small modal" id="modalAudioSend">
+        <i class="close icon"></i>
+        <div class="header">
+            Send Audio
+        </div>
+        <div class="content">
+            <form class="ui form">
+                <div class="field">
+                    <label>Type</label>
+                    <select name="type" v-model="type" aria-label="type">
+                        <option value="group">Group Message</option>
+                        <option value="user">Private Message</option>
+                    </select>
+                </div>
+                <div class="field">
+                    <label>Phone / Group ID</label>
+                    <input v-model="phone" type="text" placeholder="6289..."
+                           aria-label="phone">
+                    <input :value="phone_id" disabled aria-label="whatsapp_id">
+                </div>
+                <div class="field" style="padding-bottom: 30px">
+                    <label></label>
+                    <input type="file" class="inputfile" id="file" style="display: none"
+                           accept="audio/*"/>
+                    <label for="file" class="ui positive medium green left floated button" style="color: white">
+                        <i class="ui upload icon"></i>
+                        Upload 
+                    </label>
+                </div>
+            </form>
+        </div>
+        <div class="actions">
+            <div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
+                 @click="sendProcess">
+                Send
+                <i class="send icon"></i>
+            </div>
+        </div>
+    </div>
+    `
+}
\ No newline at end of file
diff --git a/src/views/components/SendPoll.js b/src/views/components/SendPoll.js
index d3fd683..b3551bc 100644
--- a/src/views/components/SendPoll.js
+++ b/src/views/components/SendPoll.js
@@ -3,48 +3,48 @@ export default {
     name: 'SendPoll',
     data() {
         return {
-            poll_phone: '',
-            poll_type: 'user',
-            poll_loading: false,
-            poll_question: '',
-            poll_options: ['', ''],
-            poll_max_vote: 1,
+            phone: '',
+            type: 'user',
+            loading: false,
+            question: '',
+            options: ['', ''],
+            max_vote: 1,
         }
     },
     computed: {
-        poll_phone_id() {
-            return this.poll_type === 'user' ? `${this.poll_phone}@${window.TYPEUSER}` : `${this.poll_phone}@${window.TYPEGROUP}`
+        phone_id() {
+            return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
         }
     },
     methods: {
-        sendPollModal() {
+        showModal() {
             $('#modalSendPoll').modal({
                 onApprove: function () {
                     return false;
                 }
             }).modal('show');
         },
-        async sendPollProcess() {
+        async sendProcess() {
             try {
-                let response = await this.sendPollApi()
+                let response = await this.sendApi()
                 window.showSuccessInfo(response)
                 $('#modalSendPoll').modal('hide');
             } catch (err) {
                 window.showErrorInfo(err)
             }
         },
-        sendPollApi() {
+        sendApi() {
             return new Promise(async (resolve, reject) => {
                 try {
-                    this.poll_loading = true;
+                    this.loading = true;
                     const payload = {
-                        phone: this.poll_phone_id,
-                        question: this.poll_question,
-                        max_answer: this.poll_max_vote,
-                        options: this.poll_options
+                        phone: this.phone_id,
+                        question: this.question,
+                        max_answer: this.max_vote,
+                        options: this.options
                     }
                     let response = await window.http.post(`/send/poll`, payload)
-                    this.sendPollReset();
+                    this.sendReset();
                     resolve(response.data.message)
                 } catch (error) {
                     if (error.response) {
@@ -53,26 +53,26 @@ export default {
                         reject(error.message)
                     }
                 } finally {
-                    this.poll_loading = false;
+                    this.loading = false;
                 }
             })
         },
-        sendPollReset() {
-            this.poll_phone = '';
-            this.poll_type = 'user';
-            this.poll_question = '';
-            this.poll_options = ['', ''];
-            this.poll_max_vote = 1;
+        sendReset() {
+            this.phone = '';
+            this.type = 'user';
+            this.question = '';
+            this.options = ['', ''];
+            this.max_vote = 1;
         },
-        addPollOption() {
-            this.poll_options.push('')
+        addOption() {
+            this.options.push('')
         },
-        deletePollOption(index) {
-            this.poll_options.splice(index, 1)
+        deleteOption(index) {
+            this.options.splice(index, 1)
         }
     },
     template: `
-    <div class="blue card" @click="sendPollModal()" style="cursor: pointer">
+    <div class="blue card" @click="showModal()" style="cursor: pointer">
         <div class="content">
             <a class="ui blue right ribbon label">Send</a>
             <div class="header">Send Poll</div>
@@ -92,34 +92,34 @@ export default {
             <form class="ui form">
                 <div class="field">
                     <label>Type</label>
-                    <select name="poll_type" v-model="poll_type" aria-label="type">
+                    <select name="type" v-model="type" aria-label="type">
                         <option value="group">Group Message</option>
                         <option value="user">Private Message</option>
                     </select>
                 </div>
                 <div class="field">
                     <label>Phone / Group ID</label>
-                    <input v-model="poll_phone" type="text" placeholder="6289..."
+                    <input v-model="phone" type="text" placeholder="6289..."
                            aria-label="phone">
-                    <input :value="poll_phone_id" disabled aria-label="whatsapp_id">
+                    <input :value="phone_id" disabled aria-label="whatsapp_id">
                 </div>
                 <div class="field">
                     <label>Question</label>
-                    <input v-model="poll_question" type="text" placeholder="Please enter question"
+                    <input v-model="question" type="text" placeholder="Please enter question"
                            aria-label="poll question">
                 </div>
                 <div class="field">
                     <label>Options</label>
                     <div style="display: flex; flex-direction: column; gap: 5px">
-                        <div class="ui action input" :key="index" v-for="(option, index) in poll_options">
-                            <input type="text" placeholder="Option..." v-model="poll_options[index]"
+                        <div class="ui action input" :key="index" v-for="(option, index) in options">
+                            <input type="text" placeholder="Option..." v-model="options[index]"
                                    aria-label="poll option">
-                            <button class="ui button" @click="deletePollOption(index)" type="button">
+                            <button class="ui button" @click="deleteOption(index)" type="button">
                                 <i class="minus circle icon"></i>
                             </button>
                         </div>
                         <div class="field">
-                            <button class="mini ui primary button" @click="addPollOption" type="button">
+                            <button class="mini ui primary button" @click="addOption" type="button">
                                 <i class="plus icon"></i> Option
                             </button>
                         </div>
@@ -127,14 +127,14 @@ export default {
                 </div>
                 <div class="field">
                     <label>Max Vote</label>
-                    <input v-model="poll_max_vote" type="number" placeholder="Max Vote"
+                    <input v-model="max_vote" type="number" placeholder="Max Vote"
                            aria-label="poll max votes" min="0">
                 </div>
             </form>
         </div>
         <div class="actions">
-            <div class="ui approve positive right labeled icon button" :class="{'loading': this.poll_loading}"
-                 @click="sendPollProcess" type="button">
+            <div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
+                 @click="sendProcess" type="button">
                 Send
                 <i class="send icon"></i>
             </div>
diff --git a/src/views/index.html b/src/views/index.html
index 8aef03f..7c6b0ea 100644
--- a/src/views/index.html
+++ b/src/views/index.html
@@ -133,16 +133,7 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
                 </div>
             </div>
         </div>
-        <div class="blue card" @click="sendAudioModal()" style="cursor: pointer">
-            <div class="content">
-                <a class="ui blue right ribbon label">Send</a>
-                <div class="header">Send Audio</div>
-                <div class="description">
-                    Send audio to user or group
-                </div>
-            </div>
-        </div>
-
+        <send-audio></send-audio>
         <send-poll></send-poll>
     </div>
 
@@ -151,25 +142,8 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
     </div>
 
     <div class="ui three column doubling grid cards">
-        <div class="red card" @click="messageRevokeModal()" style="cursor: pointer">
-            <div class="content">
-                <a class="ui red right ribbon label">Message</a>
-                <div class="header">Revoke Message</div>
-                <div class="description">
-                    Revoke any message in private or group chat
-                </div>
-            </div>
-        </div>
-        <div class="red card" @click="messageReactModal()" style="cursor: pointer">
-            <div class="content">
-                <a class="ui red right ribbon label">Message</a>
-                <div class="header">React Message</div>
-                <div class="description">
-                    React any message in private or group chat
-                </div>
-            </div>
-        </div>
-
+        <message-revoke></message-revoke>
+        <message-react></message-react>
         <message-update></message-update>
     </div>
 
@@ -342,47 +316,6 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
         </div>
     </div>
 
-    <!--  Modal SendAudio  -->
-    <div class="ui small modal" id="modalSendAudio">
-        <i class="close icon"></i>
-        <div class="header">
-            Send Audio
-        </div>
-        <div class="content">
-            <form class="ui form">
-                <div class="field">
-                    <label>Type</label>
-                    <select name="audio_type" v-model="audio_type" aria-label="type">
-                        <option value="group">Group Message</option>
-                        <option value="user">Private Message</option>
-                    </select>
-                </div>
-                <div class="field">
-                    <label>Phone / Group ID</label>
-                    <input v-model="audio_phone" type="text" placeholder="6289..."
-                           aria-label="phone">
-                    <input :value="audio_phone_id" disabled aria-label="whatsapp_id">
-                </div>
-                <div class="field" style="padding-bottom: 30px">
-                    <label>Audio</label>
-                    <input type="file" class="inputfile" id="audio_file" style="display: none"
-                           accept="audio/*"/>
-                    <label for="audio_file" class="ui positive medium green left floated button" style="color: white">
-                        <i class="ui upload icon"></i>
-                        Upload Audio
-                    </label>
-                </div>
-            </form>
-        </div>
-        <div class="actions">
-            <div class="ui approve positive right labeled icon button" :class="{'loading': this.audio_loading}"
-                 @click="sendAudioProcess">
-                Send
-                <i class="send icon"></i>
-            </div>
-        </div>
-    </div>
-
     <!--  Modal SendFile  -->
     <div class="ui small modal" id="modalSendFile">
         <i class="close icon"></i>
@@ -571,85 +504,6 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
         </div>
     </div>
 
-    <!--  Modal MessageRevoke  -->
-    <div class="ui small modal" id="modalMessageRevoke">
-        <i class="close icon"></i>
-        <div class="header">
-            Revoke Message
-        </div>
-        <div class="content">
-            <form class="ui form">
-                <div class="field">
-                    <label>Type</label>
-                    <select name="revoke_type" v-model="revoke_type" aria-label="type">
-                        <option value="group">Group Message</option>
-                        <option value="user">Private Message</option>
-                    </select>
-                </div>
-                <div class="field">
-                    <label>Phone / Group ID</label>
-                    <input v-model="revoke_phone" type="text" placeholder="6289..."
-                           aria-label="phone">
-                    <input :value="revoke_phone_id" disabled aria-label="whatsapp_id">
-                </div>
-                <div class="field">
-                    <label>Revoke Message ID</label>
-                    <input v-model="revoke_message_id" type="text" placeholder="Please enter your message id"
-                           aria-label="message id">
-                </div>
-            </form>
-        </div>
-        <div class="actions">
-            <div class="ui approve positive right labeled icon button" :class="{'loading': this.revoke_loading}"
-                 @click="messageRevokeProcess">
-                Send
-                <i class="send icon"></i>
-            </div>
-        </div>
-    </div>
-
-    <!--  Modal MessageReaction  -->
-    <div class="ui small modal" id="modalMessageReaction">
-        <i class="close icon"></i>
-        <div class="header">
-            React Message
-        </div>
-        <div class="content">
-            <form class="ui form">
-                <div class="field">
-                    <label>Type</label>
-                    <select name="react_type" v-model="react_type" aria-label="type">
-                        <option value="group">Group Message</option>
-                        <option value="user">Private Message</option>
-                    </select>
-                </div>
-                <div class="field">
-                    <label>Phone / Group ID</label>
-                    <input v-model="react_phone" type="text" placeholder="6289..."
-                           aria-label="phone">
-                    <input :value="react_phone_id" disabled aria-label="whatsapp_id">
-                </div>
-                <div class="field">
-                    <label>Message ID</label>
-                    <input v-model="react_message_id" type="text" placeholder="Please enter your message id"
-                           aria-label="message id">
-                </div>
-                <div class="field">
-                    <label>Emoji</label>
-                    <input v-model="react_emoji" type="text" placeholder="Please enter emoji"
-                           aria-label="message id">
-                </div>
-            </form>
-        </div>
-        <div class="actions">
-            <div class="ui approve positive right labeled icon button" :class="{'loading': this.react_loading}"
-                 @click="messageReactProcess">
-                Send
-                <i class="send icon"></i>
-            </div>
-        </div>
-    </div>
-
     <!--  Modal UserGroup  -->
     <div class="ui small modal" id="modalUserGroup">
         <i class="close icon"></i>
@@ -822,8 +676,11 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
     {{ end }}
 </script>
 <script type="module">
+    import SendAudio from "./components/SendAudio.js";
     import SendPoll from "./components/SendPoll.js";
     import MessageUpdate from "./components/MessageUpdate.js";
+    import MessageReact from "./components/MessageReact.js";
+    import MessageRevoke from "./components/MessageRevoke.js";
 
     const showErrorInfo = (message) => {
         $('body').toast({
@@ -1141,65 +998,6 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
         }
     }
 
-    const sendAudio = {
-        data() {
-            return {
-                audio_phone: '',
-                audio_type: 'user',
-                audio_loading: false,
-            }
-        },
-        computed: {
-            audio_phone_id() {
-                return this.audio_type === 'user' ? `${this.audio_phone}@${this.type_user}` : `${this.audio_phone}@${this.type_group}`
-            }
-        },
-        methods: {
-            sendAudioModal() {
-                $('#modalSendAudio').modal({
-                    onApprove: function () {
-                        return false;
-                    }
-                }).modal('show');
-            },
-            async sendAudioProcess() {
-                try {
-                    let response = await this.sendAudioApi()
-                    showSuccessInfo(response)
-                    $('#modalSendAudio').modal('hide');
-                } catch (err) {
-                    showErrorInfo(err)
-                }
-            },
-            sendAudioApi() {
-                return new Promise(async (resolve, reject) => {
-                    try {
-                        this.audio_loading = true;
-                        let payload = new FormData();
-                        payload.append("phone", this.audio_phone_id)
-                        payload.append("audio", $("#audio_file")[0].files[0])
-                        let response = await http.post(`/send/audio`, payload)
-                        this.sendAudioReset();
-                        resolve(response.data.message)
-                    } catch (error) {
-                        if (error.response) {
-                            reject(error.response.data.message)
-                        } else {
-                            reject(error.message)
-                        }
-                    } finally {
-                        this.audio_loading = false;
-                    }
-                })
-            },
-            sendAudioReset() {
-                this.audio_phone = '';
-                this.audio_type = 'user';
-                $("#audio_file").val('');
-            },
-        }
-    }
-
     const sendVideo = {
         data() {
             return {
@@ -1331,127 +1129,6 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
         }
     }
 
-    const messageRevoke = {
-        data() {
-            return {
-                revoke_type: 'user',
-                revoke_phone: '',
-                revoke_message_id: '',
-                revoke_loading: false,
-            }
-        },
-        computed: {
-            revoke_phone_id() {
-                return this.revoke_type === 'user' ? `${this.revoke_phone}@${this.type_user}` : `${this.revoke_phone}@${this.type_group}`
-            }
-        },
-        methods: {
-            messageRevokeModal() {
-                $('#modalMessageRevoke').modal({
-                    onApprove: function () {
-                        return false;
-                    }
-                }).modal('show');
-            },
-            async messageRevokeProcess() {
-                try {
-                    let response = await this.messageRevokeApi()
-                    showSuccessInfo(response)
-                    $('#modalMessageRevoke').modal('hide');
-                } catch (err) {
-                    showErrorInfo(err)
-                }
-            },
-            messageRevokeApi() {
-                return new Promise(async (resolve, reject) => {
-                    try {
-                        this.revoke_loading = true;
-                        let payload = new FormData();
-                        payload.append("phone", this.revoke_phone_id)
-                        let response = await http.post(`/message/${this.revoke_message_id}/revoke`, payload)
-                        this.messageRevokeReset();
-                        resolve(response.data.message)
-                    } catch (error) {
-                        if (error.response) {
-                            reject(error.response.data.message)
-                        } else {
-                            reject(error.message)
-                        }
-                    } finally {
-                        this.revoke_loading = false;
-                    }
-                })
-            },
-            messageRevokeReset() {
-                this.revoke_phone = '';
-                this.revoke_message_id = '';
-                this.revoke_type = 'user';
-            },
-        }
-    }
-
-    const messageReact = {
-        data() {
-            return {
-                react_type: 'user',
-                react_phone: '',
-                react_message_id: '',
-                react_emoji: '',
-                react_loading: false,
-            }
-        },
-        computed: {
-            react_phone_id() {
-                return this.react_type === 'user' ? `${this.react_phone}@${this.type_user}` : `${this.react_phone}@${this.type_group}`
-            }
-        },
-        methods: {
-            messageReactModal() {
-                $('#modalMessageReaction').modal({
-                    onApprove: function () {
-                        return false;
-                    }
-                }).modal('show');
-            },
-            async messageReactProcess() {
-                try {
-                    let response = await this.messageReactApi()
-                    showSuccessInfo(response)
-                    $('#modalMessageReaction').modal('hide');
-                } catch (err) {
-                    showErrorInfo(err)
-                }
-            },
-            messageReactApi() {
-                return new Promise(async (resolve, reject) => {
-                    try {
-                        this.react_loading = true;
-                        let payload = new FormData();
-                        payload.append("phone", this.react_phone_id)
-                        payload.append("emoji", this.react_emoji)
-                        let response = await http.post(`/message/${this.react_message_id}/reaction`, payload)
-                        this.messageReactReset();
-                        resolve(response.data.message)
-                    } catch (error) {
-                        if (error.response) {
-                            reject(error.response.data.message)
-                        } else {
-                            reject(error.message)
-                        }
-                    } finally {
-                        this.react_loading = false;
-                    }
-                })
-            },
-            messageReactReset() {
-                this.react_phone = '';
-                this.react_message_id = '';
-                this.react_emoji = '';
-                this.react_type = 'user';
-            },
-        }
-    }
-
     const sendLocation = {
         data() {
             return {
@@ -1743,8 +1420,8 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
 
     Vue.createApp({
         components: {
-            SendPoll,
-            MessageUpdate,
+            SendAudio, SendPoll,
+            MessageUpdate, MessageReact, MessageRevoke,
         },
         delimiters: ['[[', ']]'],
         data() {
@@ -1800,8 +1477,7 @@ <h1 class="ui header center aligned">[[ app_name ]]</h1>
         },
         mixins: [
             login, logout, reconnect,
-            sendMessage, sendImage, sendFile, sendVideo, sendContact, sendLocation, sendAudio,
-            messageRevoke, messageReact,
+            sendMessage, sendImage, sendFile, sendVideo, sendContact, sendLocation,
             userGroups, userPrivacy, userAvatar, userInfo
         ]
     }).mount('#app')