-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
// ----------------- FIREBASE CONFIG -----------------
const firebaseConfig = {
apiKey: "YOUR_FIREBASE_API_KEY",
authDomain: "YOUR_FIREBASE_AUTH_DOMAIN",
projectId: "YOUR_FIREBASE_PROJECT_ID",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};
firebase.initializeApp(firebaseConfig);
const auth = firebase.auth();
const db = firebase.firestore();
const messaging = firebase.messaging();
// ----------------- GLOBAL VARIABLES -----------------
let allJobs = [];
let currentUser;
// ----------------- LOGIN / SIGNUP -----------------
function signup() {
let email = document.getElementById("email").value;
let password = document.getElementById("password").value;
auth.createUserWithEmailAndPassword(email, password)
.then(() => { alert("Account created!"); })
.catch(err => alert(err.message));
}
function login() {
let email = document.getElementById("email").value;
let password = document.getElementById("password").value;
auth.signInWithEmailAndPassword(email, password)
.then(res => {
currentUser = res.user.uid;
alert("Logged in!");
loadUsers(); // load user lists for chat, rating, privacy
initMap(); // load map
})
.catch(err => alert(err.message));
}
// ----------------- POST JOB -----------------
function postJob() {
let jobText = document.getElementById("jobtext").value;
if (!jobText) return alert("Enter a job description");
navigator.geolocation.getCurrentPosition(pos => {
db.collection("jobs").add({
text: jobText,
lat: pos.coords.latitude,
lng: pos.coords.longitude,
userId: currentUser,
time: Date.now()
});
sendNotification("New Job Posted!", jobText);
});
}
// ----------------- SEARCH JOB -----------------
db.collection("jobs").onSnapshot(snapshot => {
allJobs = [];
snapshot.forEach(doc => {
allJobs.push({ id: doc.id, ...doc.data() });
});
displayJobs(allJobs);
});
function displayJobs(jobsArray) {
let list = document.getElementById("jobs");
list.innerHTML = "";
getPrivacySettings().then(settings => {
let hidden = settings.hiddenUsers || [];
let blocked = settings.blockedUsers || [];
jobsArray.forEach(job => {
if (hidden.includes(job.userId) || blocked.includes(job.userId)) return;
let li = document.createElement("li");
li.innerText = job.text;
list.appendChild(li);
});
});
}
function searchJobs() {
let query = document.getElementById("searchInput").value.toLowerCase();
let filtered = allJobs.filter(job => job.text.toLowerCase().includes(query));
displayJobs(filtered);
}
// ----------------- CHAT SYSTEM -----------------
function loadUsers() {
db.collection("users").get().then(snapshot => {
let chatSelect = document.getElementById("chatUserSelect");
let ratingSelect = document.getElementById("selectUser");
let privacySelect = document.getElementById("selectPrivacyUser");
chatSelect.innerHTML = 'Select user';
ratingSelect.innerHTML = 'Select worker';
privacySelect.innerHTML = 'Select user';
snapshot.forEach(doc => {
if(doc.id === currentUser) return;
let option = <option value="${doc.id}">${doc.data().email}</option>;
chatSelect.innerHTML += option;
ratingSelect.innerHTML += option;
privacySelect.innerHTML += option;
});
});
}
function sendMessage() {
let toUser = document.getElementById("chatUserSelect").value;
let message = document.getElementById("chatMessage").value;
if (!toUser || !message) return;
db.collection("messages").add({
sender: currentUser,
receiver: toUser,
message: message,
time: Date.now()
});
}
// ----------------- DISPLAY CHAT -----------------
db.collection("messages").onSnapshot(snapshot => {
let chatList = document.getElementById("chatList");
chatList.innerHTML = "";
snapshot.forEach(doc => {
let msg = doc.data();
if (msg.sender === currentUser || msg.receiver === currentUser) {
let li = document.createElement("li");
li.innerText = ${msg.sender === currentUser ? "You" : "User"}: ${msg.message};
chatList.appendChild(li);
}
});
});
// ----------------- STATUS / STORIES -----------------
function postStory() {
let story = document.getElementById("storytext").value;
if (!story) return;
db.collection("stories").add({
text: story,
userId: currentUser,
time: Date.now()
});
}
db.collection("stories").onSnapshot(snapshot => {
let list = document.getElementById("stories");
list.innerHTML = "";
getPrivacySettings().then(settings => {
let hidden = settings.hiddenUsers || [];
let blocked = settings.blockedUsers || [];
snapshot.forEach(doc => {
let s = doc.data();
if (hidden.includes(s.userId) || blocked.includes(s.userId)) return;
let li = document.createElement("li");
li.innerText = s.text;
list.appendChild(li);
});
});
});
// ----------------- INVITE SYSTEM -----------------
function invite() {
let link = "https://yourapp.com";
if (navigator.share) {
navigator.share({
title: "FixHelp App",
text: "Join FixHelp and find jobs or workers!",
url: link
});
} else {
alert("Copy this link: " + link);
}
}
// ----------------- MHLENGIBOT -----------------
function askMhlengiBot() {
let input = document.getElementById("mhlengiInput").value.toLowerCase();
let response = "";
if(input.includes("plumber")) response = "MhlengiBot: Try searching for plumber jobs 🔍";
else if(input.includes("job")) response = "MhlengiBot: You can post a job above to find help.";
else if(input.includes("money")) response = "MhlengiBot: Post jobs or help others to earn money 💰";
else if(input.includes("how to post")) response = "MhlengiBot: Type your job in the 'Post Job' box and click Post Job ✅";
else response = "MhlengiBot: I can help you find jobs, workers, or create posters!";
document.getElementById("mhlengiResponse").innerText = response;
}
// ----------------- WORKER RATINGS -----------------
function rateWorker() {
let workerId = document.getElementById("selectUser").value;
let rating = Number(document.getElementById("ratingSelect").value);
if(!workerId) return;
db.collection("workers").doc(workerId).collection("ratings").add({
rating: rating,
time: Date.now()
});
}
// ----------------- MAP -----------------
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: { lat: -29.8587, lng: 31.0218 } // Durban
});
db.collection("jobs").onSnapshot(snapshot => {
snapshot.forEach(doc => {
let data = doc.data();
new google.maps.Marker({
position: { lat: data.lat, lng: data.lng },
map: map,
title: data.text
});
});
});
}
// ----------------- POSTER CREATOR -----------------
function createPoster() {
let canvas = document.getElementById("posterCanvas");
let ctx = canvas.getContext("2d");
let bg = document.getElementById("bgSelect").value;
let text = document.getElementById("posterText").value;
let img = new Image();
img.src = bg;
img.onload = function() {
ctx.drawImage(img,0,0,canvas.width,canvas.height);
ctx.font = "25px Arial";
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.fillText(text, canvas.width/2, canvas.height/2);
};
}
function downloadPoster() {
let canvas = document.getElementById("posterCanvas");
let link = document.createElement('a');
link.download = 'poster.png';
link.href = canvas.toDataURL();
link.click();
}
// ----------------- PRIVACY CONTROLS -----------------
function getPrivacySettings() {
return db.collection("userSettings").doc(currentUser).get().then(doc=>{
if(doc.exists) return doc.data();
return {hiddenUsers: [], blockedUsers: []};
});
}
function hideUser() {
let userId = document.getElementById("selectPrivacyUser").value;
db.collection("userSettings").doc(currentUser).set({
hiddenUsers: firebase.firestore.FieldValue.arrayUnion(userId)
}, {merge:true});
alert("User hidden!");
}
function revealUser() {
let userId = document.getElementById("selectPrivacyUser").value;
db.collection("userSettings").doc(currentUser).update({
hiddenUsers: firebase.firestore.FieldValue.arrayRemove(userId)
});
alert("User revealed!");
}
function blockUser() {
let userId = document.getElementById("selectPrivacyUser").value;
db.collection("userSettings").doc(currentUser).set({
blockedUsers: firebase.firestore.FieldValue.arrayUnion(userId)
}, {merge:true});
alert("User blocked!");
}
// ----------------- NOTIFICATIONS -----------------
function sendNotification(title, body) {
// Requires server-side setup for FCM
console.log("Notification: ", title, body);
}