import { Timestamp } from 'firebase/firestore';
/**
* @typedef {object} AvailabilityObject
* @property {boolean} active
* @property {string} day
* @property {string} from
* @property {string} do
*/
/**
* @typedef {object} ProfileObject
* @property {AvailabilityObject[]} availability
* @property {string} phoneNumber
* @property {string} tradingSkill
*/
const defaultAvailability = [
{ day: 'Mon', from: '09:00', to: '17:00', active: false },
{ day: 'Tue', from: '09:00', to: '17:00', active: false },
{ day: 'Wed', from: '09:00', to: '17:00', active: false },
{ day: 'Thu', from: '09:00', to: '17:00', active: false },
{ day: 'Fri', from: '09:00', to: '17:00', active: false },
{ day: 'Sat', from: '10:00', to: '14:00', active: false },
{ day: 'Sun', from: '10:00', to: '14:00', active: false },
];
export class Profile {
/**
* @param {ProfileObject} rawProfileData
*/
constructor(rawProfileData) {
this.availability = rawProfileData.availability ?? defaultAvailability;
this.phoneNumber = rawProfileData.phoneNumber ?? '';
this.tradingSkill = rawProfileData.tradingSkill ?? '';
}
toObject() {
return {
availability: this.availability,
phoneNumber: this.phoneNumber,
tradingSkill: this.tradingSkill,
};
}
}
/**
* @typedef {Object} UserObject
* @property {string} uid - The user's UID
* @property {string} bio - The user's bio?
* @property {string} location - The user's current location
* @property {String[]} skillsOffered The skills the user is offering
* @property {String[]} skillsWanted The skills the user is looking for
* @property {Profile} profile The profile data of the user
* @property {Number} rating - The user's rating
* @property {Object} availability - The availability of the user
* @property {object} profile
*/
export class User {
/**
* @param {UserObject} user
*/
constructor(user) {
this.uid = user.uid;
this.bio = user.bio;
this.location = user.location;
this.skillsOffered = user.skillsOffered;
this.skillsWanted = user.skillsWanted;
this.rating = user.rating;
/** @deprecated See User.profile */
this.availability = user.availability;
this.profile = new Profile(user.profile || {});
}
/**
* Convert this User instance into a plain object for Firestore.
* @returns {UserObject}
*/
toObject() {
return {
uid: this.uid,
bio: this.bio,
location: this.location,
skillsOffered: this.skillsOffered,
skillsWanted: this.skillsWanted,
rating: this.rating,
availability: this.availability,
profile: this.profile,
};
}
}
/**
* @typedef {'pending' | 'accepted' | 'declined' | 'completed' | 'canceled'} TradeStatus
*/
/**
* @typedef {Object} TradeObject
* @property {String} id
* @property {String} offererId
* @property {String} receiverId
* @property {String} offeredSkill
* @property {String} requestedSkill
* @property {TradeStatus} tradeStatus
* @property {String} message
*/
// TODO: Define what a Trade looks like.
export class Trade {
/**
* @param {TradeObject} trade
*/
constructor(trade) {
this.id = trade.id;
this.offererId = trade.offererId;
this.receiverId = trade.receiverId;
this.offeredSkill = trade.offeredSkill;
this.requestedSkill = trade.requestedSkill;
this.tradeStatus = trade.tradeStatus;
this.message = trade.message;
}
toObject() {
return {
id: this.id,
offererId: this.offererId,
receiverId: this.receiverId,
offeredSkill: this.offeredSkill,
requestedSkill: this.requestedSkill,
tradeStatus: this.tradeStatus,
message: this.message,
};
}
}
/**
* Chat
*/
/**
* @typedef {Object} ChatParticipant
* @property {string} displayName
* @property {string} id
* @property {string} avatar
*/
/**
* @typedef {Object} MessageObject
* @property {string} id
* @property {ChatParticipant} author
* @property {string} chatId
* @property {string} content
* @property {import('firebase/firestore').Timestamp} timestamp
*/
/**
* @typedef {Object} ChatObject
* @property {string} id Generated by Firebase.
* @property {ChatParticipant} participant1
* @property {ChatParticipant} participant2
* @property {MessageObject[]} messages
* @property {'active' | 'closed'} status
*/
export class Message {
/**
* @param {MessageObject} rawData
*/
constructor(rawData) {
this.id = rawData.id;
this.author = new ChatUser(rawData.author);
this.chatId = rawData.chatId;
this.content = rawData.content;
this.timestamp = rawData.timestamp ?? Timestamp.now();
}
toObject() {
return {
id: this.id,
author: this.author.toObject(),
chatId: this.chatId,
content: this.content,
timestamp: this.timestamp,
};
}
}
export class ChatUser {
/**
*
* @param {ChatParticipant} rawData
*/
constructor(rawData) {
this.displayName = rawData.displayName;
this.avatar = rawData.avatar;
this.id = rawData.id;
}
toObject() {
return {
displayName: this.displayName,
avatar: this.avatar,
id: this.id,
};
}
/**
* @param {import('firebase/auth').User} user
*/
static from(user) {
return new ChatUser({
avatar: user.photoURL,
displayName: user.displayName,
id: user.uid,
});
}
}
export class Chat {
/**
* @param {ChatObject} rawData - The Firebase Raw Data
*/
constructor(rawData) {
this.id = rawData.id;
this.participant1 = new ChatUser(rawData.participant1);
this.participant2 = new ChatUser(rawData.participant2);
this.status = rawData.status;
this.messages = [];
rawData.messages.forEach((msg) => {
this.messages.push(new Message(msg));
});
}
/**
* @param {Message} messageData
*/
createMessage(messageData) {
if (this.status == 'closed') return;
this.messages.push(messageData);
// need to push to firebase.
return;
}
close() {
this.status = 'closed';
return;
}
toObject() {
const firebaseMessages = [];
this.messages.forEach((msg) => {
firebaseMessages.push(msg.toObject());
});
return {
id: this.id,
participant1: this.participant1.toObject(),
participant2: this.participant2.toObject(),
status: this.status,
messages: firebaseMessages,
};
}
}