seeding initial office rooms and showing them
This commit is contained in:
@@ -55,8 +55,6 @@ export default function Announcements() {
|
|||||||
updatedOrNewAnn.id = change.doc.id;
|
updatedOrNewAnn.id = change.doc.id;
|
||||||
|
|
||||||
if (change.type === "added" || change.type === "modified") {
|
if (change.type === "added" || change.type === "modified") {
|
||||||
console.log("New or updated announcement: ", updatedOrNewAnn);
|
|
||||||
|
|
||||||
// update rooms map
|
// update rooms map
|
||||||
setAnnMap((prevMap) => {
|
setAnnMap((prevMap) => {
|
||||||
return new Map(prevMap.set(updatedOrNewAnn.id, updatedOrNewAnn));
|
return new Map(prevMap.set(updatedOrNewAnn.id, updatedOrNewAnn));
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import {
|
||||||
|
collection,
|
||||||
|
getFirestore,
|
||||||
|
onSnapshot,
|
||||||
|
query,
|
||||||
|
where,
|
||||||
|
} from "firebase/firestore";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useAuth } from "../../contexts/authContext";
|
||||||
|
import { useTeamDashboardContext } from "../../contexts/teamDashboardContext";
|
||||||
|
import OfficeRoom from "../../models/officeRoom";
|
||||||
|
import { Collections } from "../../services/collections";
|
||||||
|
import OfficeRoomService from "../../services/officeRoomService";
|
||||||
|
import OfficeCard from "../OfficeCard";
|
||||||
|
|
||||||
|
const db = getFirestore();
|
||||||
|
|
||||||
|
const officeRoomService = new OfficeRoomService();
|
||||||
|
|
||||||
|
export default function Office() {
|
||||||
|
const { currUser } = useAuth();
|
||||||
|
const { team } = useTeamDashboardContext();
|
||||||
|
|
||||||
|
const [officeRoomsMap, setOfficeRoomsMap] = useState<Map<string, OfficeRoom>>(
|
||||||
|
new Map<string, OfficeRoom>()
|
||||||
|
);
|
||||||
|
|
||||||
|
// get all offices for this team : realtime
|
||||||
|
useEffect(() => {
|
||||||
|
/**
|
||||||
|
* QUERY:
|
||||||
|
* all offices for this team
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const q = query(
|
||||||
|
collection(db, Collections.officeRooms),
|
||||||
|
where("teamId", "==", team.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
// return unsubscribe
|
||||||
|
return onSnapshot(q, (snapshot) => {
|
||||||
|
if (snapshot.empty) {
|
||||||
|
// seed data and create the initial rooms
|
||||||
|
console.log("seeding office rooms for this team");
|
||||||
|
officeRoomService.createInitialOfficeRooms(currUser.uid, team.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.docChanges().forEach((change) => {
|
||||||
|
let updatedOfficeRoom = change.doc.data() as OfficeRoom;
|
||||||
|
updatedOfficeRoom.id = change.doc.id;
|
||||||
|
|
||||||
|
if (change.type === "added" || change.type === "modified") {
|
||||||
|
// update office rooms map on change of the room
|
||||||
|
setOfficeRoomsMap((prevMap) => {
|
||||||
|
return new Map(
|
||||||
|
prevMap.set(updatedOfficeRoom.id, updatedOfficeRoom)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (change.type === "removed") {
|
||||||
|
console.log("Removed office room: ", updatedOfficeRoom);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const allOfficeRooms = Array.from(officeRoomsMap.values());
|
||||||
|
|
||||||
|
allOfficeRooms.sort((a, b) => {
|
||||||
|
if (a.name < b.name) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.name > b.name) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// if there are none, then show user button to create initial office rooms and then create them
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="p-5 flex flex-col bg-gray-100 bg-opacity-25 rounded-lg shadow-md w-96 shrink-0">
|
||||||
|
<span className="flex flex-row justify-start items-center pb-5">
|
||||||
|
<span className="flex flex-col">
|
||||||
|
<span className="text-white uppercase">Office</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{/* all office rooms */}
|
||||||
|
<span className="flex flex-col space-y-5">
|
||||||
|
{allOfficeRooms.map((officeRoom) => (
|
||||||
|
<OfficeCard key={officeRoom.id} officeRoom={officeRoom} />
|
||||||
|
))}
|
||||||
|
{/* <OfficeCard /> */}
|
||||||
|
</span>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -204,7 +204,7 @@ export default function TeamVoiceLine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="p-5 flex flex-col bg-gray-100 bg-opacity-25 rounded-lg shadow-md w-96 shrink-0 max-h-[32rem]">
|
<section className="p-5 flex flex-col bg-gray-100 bg-opacity-25 rounded-lg shadow-md w-96 shrink-0">
|
||||||
<span className="flex flex-row justify-start items-center pb-5">
|
<span className="flex flex-row justify-start items-center pb-5">
|
||||||
<span className="flex flex-col">
|
<span className="flex flex-col">
|
||||||
<span className="text-white">TEAM</span>
|
<span className="text-white">TEAM</span>
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { Avatar } from "antd";
|
||||||
|
import OfficeRoom, { OfficeRoomState } from "../models/officeRoom";
|
||||||
|
|
||||||
|
interface IOfficeCard {
|
||||||
|
officeRoom: OfficeRoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function OfficeCard(props: IOfficeCard) {
|
||||||
|
return (
|
||||||
|
<span className="flex flex-col">
|
||||||
|
<span className="flex flex-row justify-start items-center">
|
||||||
|
{renderOfficePulse(OfficeRoomState.active)}
|
||||||
|
|
||||||
|
{/* office location name */}
|
||||||
|
<span className="text-gray-200 text-lg font-semibold ml-2">
|
||||||
|
{props.officeRoom.name}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{/* all members in room */}
|
||||||
|
<span className="ml-auto">
|
||||||
|
<Avatar.Group>
|
||||||
|
{props.officeRoom.members.map((officeLocation) => {
|
||||||
|
<Avatar
|
||||||
|
style={{ backgroundColor: "teal", verticalAlign: "middle" }}
|
||||||
|
className="shadow-xl hover:z-20 hover:cursor-pointer"
|
||||||
|
>
|
||||||
|
{officeLocation[0]}
|
||||||
|
</Avatar>;
|
||||||
|
})}
|
||||||
|
</Avatar.Group>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOfficePulse(officeRoomState: OfficeRoomState) {
|
||||||
|
return (
|
||||||
|
<span className="h-4 w-4 rounded-full bg-green-500 animate-pulse shadow-lg"></span>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Timestamp } from "firebase/firestore";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
|
export default class OfficeRoom {
|
||||||
|
id: string = uuidv4();
|
||||||
|
|
||||||
|
teamId: string;
|
||||||
|
|
||||||
|
name: string; // entrance, kitchen, etc.
|
||||||
|
|
||||||
|
createdDate: Timestamp;
|
||||||
|
createdByUserId: string;
|
||||||
|
|
||||||
|
lastUpdatedDate: Timestamp;
|
||||||
|
|
||||||
|
members: string[] = []; // id's of users in the office room
|
||||||
|
|
||||||
|
state: OfficeRoomState;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
_name: string,
|
||||||
|
_teamId: string,
|
||||||
|
_createdBy: string,
|
||||||
|
_state: OfficeRoomState = OfficeRoomState.idle
|
||||||
|
) {
|
||||||
|
this.name = _name;
|
||||||
|
this.teamId = _teamId;
|
||||||
|
this.createdByUserId = _createdBy;
|
||||||
|
this.state = _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OfficeRoomState {
|
||||||
|
active = "active",
|
||||||
|
idle = "idle",
|
||||||
|
archived = "archived",
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import TeamService from "../../services/teamService";
|
|||||||
import UserService from "../../services/userService";
|
import UserService from "../../services/userService";
|
||||||
import Announcements from "../../components/Dashboard/Announcements";
|
import Announcements from "../../components/Dashboard/Announcements";
|
||||||
import Links from "../../components/Dashboard/Links";
|
import Links from "../../components/Dashboard/Links";
|
||||||
|
import Office from "../../components/Dashboard/Office";
|
||||||
|
|
||||||
// User has switched back to the tab
|
// User has switched back to the tab
|
||||||
const onFocus = () => {
|
const onFocus = () => {
|
||||||
@@ -87,6 +88,8 @@ function TeamDashboard() {
|
|||||||
<div className="flex flex-row items-baseline space-x-5 space-y-5">
|
<div className="flex flex-row items-baseline space-x-5 space-y-5">
|
||||||
<div className="flex flex-col max-w-sm space-y-5">
|
<div className="flex flex-col max-w-sm space-y-5">
|
||||||
<TeamVoiceLine />
|
<TeamVoiceLine />
|
||||||
|
|
||||||
|
<Office />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col space-y-5 flex-1 overflow-auto">
|
<div className="flex flex-col space-y-5 flex-1 overflow-auto">
|
||||||
|
|||||||
@@ -8,4 +8,6 @@ export enum Collections {
|
|||||||
rooms = "rooms",
|
rooms = "rooms",
|
||||||
announcements = "announcements",
|
announcements = "announcements",
|
||||||
links = "links",
|
links = "links",
|
||||||
|
|
||||||
|
officeRooms = "officeRooms",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
addDoc,
|
||||||
|
collection,
|
||||||
|
doc,
|
||||||
|
FieldValue,
|
||||||
|
Firestore,
|
||||||
|
getFirestore,
|
||||||
|
serverTimestamp,
|
||||||
|
setDoc,
|
||||||
|
writeBatch,
|
||||||
|
} from "firebase/firestore";
|
||||||
|
import OfficeRoom from "../models/officeRoom";
|
||||||
|
import { Collections } from "./collections";
|
||||||
|
|
||||||
|
export default class OfficeRoomService {
|
||||||
|
private db: Firestore = getFirestore();
|
||||||
|
private batch = writeBatch(this.db);
|
||||||
|
|
||||||
|
async createInitialOfficeRooms(createdByUserId: string, teamId: string) {
|
||||||
|
const entrance = new OfficeRoom("Entrance", teamId, createdByUserId);
|
||||||
|
const kitchen = new OfficeRoom("Kitchen", teamId, createdByUserId);
|
||||||
|
const hallway = new OfficeRoom("Hallway", teamId, createdByUserId);
|
||||||
|
const corner = new OfficeRoom("Corner", teamId, createdByUserId);
|
||||||
|
const main = new OfficeRoom("Team Hub", teamId, createdByUserId);
|
||||||
|
const handsOnDeck = new OfficeRoom(
|
||||||
|
"All Hand On Deck",
|
||||||
|
teamId,
|
||||||
|
createdByUserId
|
||||||
|
);
|
||||||
|
|
||||||
|
const initialORs: OfficeRoom[] = [
|
||||||
|
entrance,
|
||||||
|
kitchen,
|
||||||
|
hallway,
|
||||||
|
corner,
|
||||||
|
main,
|
||||||
|
handsOnDeck,
|
||||||
|
];
|
||||||
|
|
||||||
|
initialORs.forEach((oR) => {
|
||||||
|
const oRRef = doc(this.db, Collections.officeRooms, oR.id);
|
||||||
|
this.batch.set(oRRef, { ...oR, createdDate: serverTimestamp() });
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.batch.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// async createOrUpdateRoom(room: Room) {
|
||||||
|
// if (room.id) {
|
||||||
|
// //update
|
||||||
|
// await this.updateRoom(room);
|
||||||
|
// } else {
|
||||||
|
// //create
|
||||||
|
// const roomDocRef = await addDoc(collection(this.db, Collections.rooms), {
|
||||||
|
// ...room,
|
||||||
|
// createdDate: serverTimestamp(),
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async updateMembersInRoom(roomId: string, newMembersInRoom: string[]) {
|
||||||
|
// // if the room is going to be empty, then change status accordingly
|
||||||
|
// var status: RoomStatus = RoomStatus.live;
|
||||||
|
// if (newMembersInRoom.length == 0) {
|
||||||
|
// status = RoomStatus.empty;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const docRef = doc(this.db, Collections.rooms, roomId);
|
||||||
|
// await setDoc(
|
||||||
|
// docRef,
|
||||||
|
// {
|
||||||
|
// status,
|
||||||
|
// membersInRoom: newMembersInRoom,
|
||||||
|
// lastUpdatedDate: serverTimestamp(),
|
||||||
|
// },
|
||||||
|
// { merge: true }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async updateRoom(room: Room) {
|
||||||
|
// const docRef = doc(this.db, Collections.rooms, room.id);
|
||||||
|
// await setDoc(
|
||||||
|
// docRef,
|
||||||
|
// { ...room, lastUpdatedDate: serverTimestamp() },
|
||||||
|
// { merge: true }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user