Compare commits

...

14 Commits

24 changed files with 423 additions and 1 deletions

7
.env Normal file
View File

@ -0,0 +1,7 @@
VUE_APP_FIREBASE_API_KEY=YOUR_API_KEY
VUE_APP_FIREBASE_AUTH_DOMAIN=YOUR_AUTH_DOMAIN
VUE_APP_FIREBASE_PROJECT_ID=YOUR_PROJECT_ID
VUE_APP_FIREBASE_STORAGE_BUCKET=YOUR_STORAGE_BUCKET
VUE_APP_FIREBASE_MESSAGING_SENDER_ID=YOUR_MESSAGING_SENDER_ID
VUE_APP_FIREBASE_APP_ID=YOUR_APP_ID
# Disini We Belum Uji Sama Sekali Nunggu nanti aja lah

0
.gitignore vendored Normal file
View File

0
FrontEnd/app.js Executable file
View File

0
FrontEnd/components/ChatBox.js Executable file
View File

0
FrontEnd/components/Message.js Executable file
View File

0
FrontEnd/components/Navbar.js Executable file
View File

122
FrontEnd/css/style.css Executable file
View File

@ -0,0 +1,122 @@
/* Global Styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f0f2f5;
color: #333;
}
#app {
width: 100%;
max-width: 420px;
border: 1px solid #ddd;
border-radius: 10px;
overflow: hidden;
background-color: #fff;
display: flex;
flex-direction: column;
height: 90vh;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
/* Header */
header {
background-color: #075e54;
color: #fff;
padding: 10px;
display: flex;
align-items: center;
justify-content: space-between;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.settings-btn {
font-size: 18px;
background: none;
border: none;
color: white;
cursor: pointer;
}
/* Chat Box */
#chat-box {
flex: 1;
padding: 15px;
overflow-y: auto;
background-color: #e5ddd5;
}
.message {
max-width: 75%;
margin-bottom: 10px;
padding: 10px;
border-radius: 8px;
font-size: 14px;
line-height: 1.4;
position: relative;
}
.message.sent {
background-color: #dcf8c6;
align-self: flex-end;
text-align: right;
}
.message.received {
background-color: #fff;
align-self: flex-start;
text-align: left;
}
/* Message Form */
#message-form {
display: flex;
align-items: center;
padding: 10px;
background-color: #f0f2f5;
border-top: 1px solid #ddd;
}
#message-input {
flex: 1;
padding: 10px;
font-size: 16px;
border: 1px solid #ddd;
border-radius: 20px;
margin-right: 10px;
outline: none;
}
button {
padding: 10px 15px;
font-size: 20px;
color: #fff;
background-color: #075e54;
border: none;
border-radius: 50%;
cursor: pointer;
}
/* Responsive Design */
@media (max-width: 480px) {
#app {
height: 100vh;
max-width: 100%;
border-radius: 0;
}
}

30
FrontEnd/index.html Executable file
View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChatsApp</title>
<link rel="stylesheet" href="css/style.css">
<!-- Font BOXICO-->
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
</head>
<body>
<div id="app">
<header>
<div class="header-content">
<h1>ChatsApp</h1>
<button class="settings-btn"><i class='bx bx-cog'></i></button> <!-- Disini we tambahin font icon biar gak manul lu bikin icon pake emote dari keyboard njir :| -->
</div>
</header>
<main>
<section id="chat-box"></section>
<form id="message-form">
<input type="text" id="message-input" placeholder="Type a message...">
<button type="submit"></button>
</form>
</main>
</div>
<script src="js/main.js"></script>
</body>
</html>

29
FrontEnd/js/main.js Executable file
View File

@ -0,0 +1,29 @@
document.addEventListener("DOMContentLoaded", () => {
const chatBox = document.getElementById("chat-box");
const messageForm = document.getElementById("message-form");
const messageInput = document.getElementById("message-input");
// Function to add message to chat box
function addMessage(text, type) {
const messageElement = document.createElement("div");
messageElement.textContent = text;
messageElement.classList.add("message", type);
chatBox.appendChild(messageElement);
chatBox.scrollTop = chatBox.scrollHeight;
}
// Handle message send
messageForm.addEventListener("submit", (e) => {
e.preventDefault();
const messageText = messageInput.value.trim();
if (messageText !== "") {
addMessage(messageText, "sent");
messageInput.value = "";
// Simulate received message after 1 second
setTimeout(() => {
addMessage("This is an auto-reply!", "received");
}, 1000);
}
});
});

0
FrontEnd/services/api.js Executable file
View File

0
FrontEnd/style.css Executable file
View File

3
README.md Normal file → Executable file
View File

@ -1,3 +1,6 @@
# ChatsApp
ChatsApp The Project Real Time Chating
Install: `npm install`
Run : `npm serve`

0
package.json Normal file
View File

0
public/index.html Normal file
View File

63
src/App.vue Normal file
View File

@ -0,0 +1,63 @@
<template>
<div id="app">
<button v-if="!user" @click="login">Login with Google</button>
<div v-else>
<p>Welcome, {{ user.displayName }}!</p>
<ChatBox />
<button @click="logout">Logout</button>
</div>
</div>
</template>
<script>
import { ref, onMounted } from "vue";
import { signInWithGoogle, signOutUser } from "./firebase/auth";
import ChatBox from "./components/ChatBox.vue";
export default {
components: {
ChatBox,
},
setup() {
const user = ref(null);
// Fungsi login Google
const login = async () => {
const loggedInUser = await signInWithGoogle();
if (loggedInUser) {
user.value = loggedInUser;
localStorage.setItem("user", JSON.stringify(loggedInUser));
}
};
// Fungsi logout
const logout = () => {
signOutUser();
user.value = null;
localStorage.removeItem("user");
};
// Periksa status login saat pertama kali dimuat
onMounted(() => {
const savedUser = localStorage.getItem("user");
if (savedUser) {
user.value = JSON.parse(savedUser);
}
});
return { user, login, logout };
},
};
</script>
<style scoped>
/* Tambahkan gaya untuk App.vue */
#app {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
}
</style>

View File

@ -0,0 +1,80 @@
<!-- src/components/ChatBox.vue -->
<template>
<div class="chatbox">
<ul class="message-list">
<Message
v-for="message in messages"
:key="message.id"
:message="message"
/>
</ul>
<input
v-model="newMessage"
@keyup.enter="sendMessage"
placeholder="Type a message"
/>
<button @click="sendMessage">Send</button>
</div>
</template>
<script>
import { ref } from "vue";
import Message from "./Message.vue";
import { sendMessage, listenForMessages } from "../firebase/database";
export default {
components: {
Message,
},
setup() {
const messages = ref([]);
const newMessage = ref("");
// Mendengarkan pesan secara real-time
listenForMessages((loadedMessages) => {
messages.value = loadedMessages;
});
// Fungsi untuk mengirim pesan
const sendMessageHandler = () => {
if (newMessage.value.trim()) {
sendMessage(newMessage.value);
newMessage.value = "";
}
};
return {
messages,
newMessage,
sendMessage: sendMessageHandler,
};
},
};
</script>
<style scoped>
/* Tambahkan gaya untuk komponen chatbox */
.chatbox {
display: flex;
flex-direction: column;
width: 100%;
max-width: 600px;
margin: 0 auto;
}
.message-list {
flex: 1;
list-style-type: none;
padding: 0;
margin: 0;
overflow-y: auto;
}
input {
width: 100%;
padding: 8px;
margin-top: 10px;
box-sizing: border-box;
}
</style>

View File

@ -0,0 +1,25 @@
<!-- src/components/Message.vue -->
<template>
<li class="message">
<strong>{{ message.sender }}:</strong> {{ message.text }}
</li>
</template>
<script>
export default {
props: {
message: Object,
},
};
</script>
<style scoped>
/* Tambahkan gaya untuk pesan individual */
.message {
margin-bottom: 10px;
padding: 5px;
border-radius: 5px;
background-color: #f1f1f1;
}
</style>

14
src/firebase/auth.js Normal file
View File

@ -0,0 +1,14 @@
// src/firebase/auth.js
import { getAuth, signOut } from "firebase/auth";
import app from "./firebaseConfig";
const auth = getAuth(app);
export const signOutUser = async () => {
try {
await signOut(auth);
console.log("User logged out");
} catch (error) {
console.error("Error during logout:", error);
}
};

35
src/firebase/database.js Normal file
View File

@ -0,0 +1,35 @@
// src/firebase/database.js
import { getFirestore, collection, addDoc, onSnapshot, query, orderBy } from "firebase/firestore";
import app from "./firebaseConfig";
const db = getFirestore(app);
const messagesRef = collection(db, "messages");
// Fungsi untuk mengirim pesan
export const sendMessage = async (text) => {
try {
const user = JSON.parse(localStorage.getItem("user"));
if (!user) return;
await addDoc(messagesRef, {
text,
sender: user.displayName,
uid: user.uid,
timestamp: new Date(),
});
} catch (error) {
console.error("Error adding message: ", error);
}
};
// Mendengarkan pesan secara real-time
export const listenForMessages = (callback) => {
const q = query(messagesRef, orderBy("timestamp"));
onSnapshot(q, (snapshot) => {
const messages = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
callback(messages);
});
};

View File

@ -0,0 +1,14 @@
// src/firebase/firebaseConfig.js
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: process.env.VUE_APP_FIREBASE_API_KEY,
authDomain: process.env.VUE_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.VUE_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.VUE_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.VUE_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.VUE_APP_FIREBASE_APP_ID,
};
const app = initializeApp(firebaseConfig);
export default app;

0
src/main.js Normal file
View File

0
src/router/index.js Normal file
View File

0
src/store/index.js Normal file
View File

0
src/views/ChatRoom.vue Normal file
View File