From 90d865e77a42ecd7a15a26de3f9b1b71c4c079e3 Mon Sep 17 00:00:00 2001 From: Josh Daniel Date: Wed, 2 Mar 2022 21:24:07 +0800 Subject: [PATCH 01/17] fix: update quotations --- src/utils/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 51e4a8d..0d7dcaf 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -19,13 +19,13 @@ export const aboutPage = { export const landingPage = { body1: - 'Every now and then, someone would pop in the group chat and say: "What assignments do we have? When is it due?" With this web app, you can track tasks collaboratively with your peers!', + 'Every now and then, someone would pop in the group chat and say: "What assignments do we have? When is it due?" With this web app, you can track tasks collaboratively with your peers!', body2: 'trackAsOne is a responsive web-based app that enables students to track homework & activities together with their friends or classmates. Forgot about a homework? Your friends got your back!', body3: - 'Tasks given by teachers are usually on different platforms. Few examples are Messenger and MS Teams. The problem is that they are usually cluttered with conversations making it hard to scroll back and you have to check multiple platforms just to make sure you won't miss an assignment.', + "Tasks given by teachers are usually on different platforms. Few examples are Messenger and MS Teams. The problem is that they are usually cluttered with conversations making it hard to scroll back and you have to check multiple platforms just to make sure you won't miss an assignment.", }; export const socials = [ From d7f5432b24a990812f1397b0792f6b32250227ba Mon Sep 17 00:00:00 2001 From: Josh Daniel Date: Wed, 2 Mar 2022 21:38:04 +0800 Subject: [PATCH 02/17] style: minor changes --- pages/room.tsx | 2 +- src/components/Input.tsx | 2 +- styles/tailwind.css | 6 +++--- tailwind.config.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pages/room.tsx b/pages/room.tsx index c757dfd..0da007d 100644 --- a/pages/room.tsx +++ b/pages/room.tsx @@ -145,7 +145,7 @@ const Room = () => { }} className='w-full mt-4' > -
+
); diff --git a/styles/tailwind.css b/styles/tailwind.css index 205b1f3..4fd05b5 100644 --- a/styles/tailwind.css +++ b/styles/tailwind.css @@ -24,7 +24,7 @@ } .room-input { - @apply bg-inputbg h-[45px] outline-none w-full text-sm md:text-base; + @apply bg-[#f5f5f5] h-[45px] outline-none w-full text-sm md:text-base; } .room-input-btn { @@ -36,7 +36,7 @@ } .room-input-container { - @apply px-4 rounded bg-inputbg text-primary placeholder-inputfg focus-within:border-primary border-2 w-full; + @apply px-4 rounded bg-[#f9f9f9] text-primary placeholder-inputfg focus-within:border-primary border-2 w-full; } .popup-proceed { @@ -72,6 +72,6 @@ } .about-h1 { - @apply text-xl md:text-3xl font-semibold mb-4; + @apply md:text-3xl font-semibold mb-4; } } diff --git a/tailwind.config.js b/tailwind.config.js index 90a653a..2ecc17a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -7,7 +7,7 @@ module.exports = { f9: '#F9F9F9', primary: '#2B2B2B', secondary: '#E3B04B', - inputbg: '#F5F5F5', + inputbg: '#E7E7E7', inputfg: '#B5B3B1', }, From ee6b796883fc3db3112ccd9fdcf766a58585729f Mon Sep 17 00:00:00 2001 From: Josh Daniel Date: Wed, 2 Mar 2022 22:17:45 +0800 Subject: [PATCH 03/17] refactor: extract join & create page to component --- pages/create.tsx | 37 ++++--------- pages/join.tsx | 37 +++++-------- pages/room.tsx | 2 +- ...{PendingContainer.tsx => Confirmation.tsx} | 6 +-- src/components/Home/Invitation.tsx | 6 +-- src/components/Modal.tsx | 8 +-- src/components/Room/Info.tsx | 4 +- src/components/Room/Task.tsx | 8 +-- src/components/Room/UserRequest.tsx | 6 +-- src/components/RoomInput.tsx | 52 +++++++++++++++++++ src/components/index.ts | 3 +- 11 files changed, 96 insertions(+), 73 deletions(-) rename src/components/{PendingContainer.tsx => Confirmation.tsx} (86%) create mode 100644 src/components/RoomInput.tsx diff --git a/pages/create.tsx b/pages/create.tsx index 703a0f2..14888d1 100644 --- a/pages/create.tsx +++ b/pages/create.tsx @@ -8,10 +8,9 @@ import { doc, setDoc, serverTimestamp } from 'firebase/firestore'; import { db } from '@/config/firebase'; import { useCreatedRooms } from '@/services'; -import { Button } from '@/components/Button'; import { useAuth } from '@/context/AuthContext'; +import { Layout, RoomInput } from '@/components'; import { NextPageWithLayout } from '@/types/page'; -import { Header, Input, Layout } from '@/components'; const Create: NextPageWithLayout = () => { const [roomName, setRoomName] = useState(''); @@ -51,31 +50,15 @@ const Create: NextPageWithLayout = () => { }; return ( - <> -
-
- setRoomName(e.target.value)} - value={roomName} - placeholder='enter room name' - minLength={5} - maxLength={15} - /> - -
-
-
- + setRoomName(e.target.value)} + value={roomName} + placeholder='enter room name' + /> ); }; diff --git a/pages/join.tsx b/pages/join.tsx index e146413..fd59101 100644 --- a/pages/join.tsx +++ b/pages/join.tsx @@ -6,7 +6,7 @@ import { arrayUnion, doc, getDoc, updateDoc } from 'firebase/firestore'; import { db } from '@/config/firebase'; import Layout from '@/components/Layout'; -import { Header, Input } from '@/components'; +import { RoomInput } from '@/components'; import { useAuth } from '@/context/AuthContext'; import { NextPageWithLayout } from '@/types/page'; @@ -17,7 +17,8 @@ const Join: NextPageWithLayout = () => { data: { id }, } = useAuth(); - const requestJoin = async () => { + const requestJoin = async (e: React.FormEvent) => { + e.preventDefault(); setRoomID(''); const roomRef = doc(db, 'rooms', roomId); @@ -46,29 +47,15 @@ const Join: NextPageWithLayout = () => { }; return ( - <> -
-
- setRoomID(e.target.value)} - value={roomId} - placeholder='enter room id' - minLength={5} - maxLength={15} - /> - -
- -
-
- + setRoomID(e.target.value)} + value={roomId} + placeholder='enter room id' + /> ); }; diff --git a/pages/room.tsx b/pages/room.tsx index 0da007d..89967bb 100644 --- a/pages/room.tsx +++ b/pages/room.tsx @@ -163,7 +163,7 @@ const Room = () => { setModal(false)} + setIsOpen={setModal} title='Add Task' proceed={addTask} isLoading={loading} diff --git a/src/components/PendingContainer.tsx b/src/components/Confirmation.tsx similarity index 86% rename from src/components/PendingContainer.tsx rename to src/components/Confirmation.tsx index 9169077..3e14fa2 100644 --- a/src/components/PendingContainer.tsx +++ b/src/components/Confirmation.tsx @@ -3,12 +3,12 @@ import { BsFillCheckCircleFill } from 'react-icons/bs'; import { IoCloseCircle } from 'react-icons/io5'; import { SideBtn } from './Button'; -interface PendingContainerProps { +interface ConfirmationProps { check: () => void; close: () => void; } -const PendingContainer: React.FC = ({ +const Confirmation: React.FC = ({ check, close, children, @@ -36,4 +36,4 @@ const PendingContainer: React.FC = ({ ); }; -export default PendingContainer; +export default Confirmation; diff --git a/src/components/Home/Invitation.tsx b/src/components/Home/Invitation.tsx index 9d606dc..84fbc79 100644 --- a/src/components/Home/Invitation.tsx +++ b/src/components/Home/Invitation.tsx @@ -6,7 +6,7 @@ import { arrayRemove, arrayUnion, doc, updateDoc } from 'firebase/firestore'; import { useRoom } from '@/services'; import { db } from '@/config/firebase'; -import PendingContainer from '../PendingContainer'; +import Confirmation from '../Confirmation'; interface InvitationProps { roomId: string; @@ -56,14 +56,14 @@ const Invitation = ({ roomId, user }: InvitationProps) => { }; return ( - +

{room?.name}

room id: {room?.id}

-
+ ); }; diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index 77b9a95..df55ea8 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -11,7 +11,7 @@ interface ModalProps { isOpen: boolean; href?: string; proceed?: () => void; - dismiss: () => void; + setIsOpen: React.Dispatch>; isLoading?: boolean; empty?: boolean; } @@ -24,7 +24,7 @@ const Modal = ({ isOpen, href, proceed, - dismiss, + setIsOpen, isLoading, empty, }: ModalProps) => { @@ -33,7 +33,7 @@ const Modal = ({
setIsOpen(false)} className='md:text-2xl' > diff --git a/src/components/Room/Info.tsx b/src/components/Room/Info.tsx index 5e020ba..0fc02b2 100644 --- a/src/components/Room/Info.tsx +++ b/src/components/Room/Info.tsx @@ -90,7 +90,7 @@ const Info: React.FC = () => { title='Delete Room' description='Are you sure you want to delete this room? This action cannot be undone.' proceed={deleteRoom} - dismiss={() => setDeleteModal(false)} + setIsOpen={setDeleteModal} isOpen={deleteModal} /> @@ -98,7 +98,7 @@ const Info: React.FC = () => { title='Leave Room' description='Are you sure you want to leave this room? You need to request or get an invite before you can join again.' proceed={leaveRoom} - dismiss={() => setLeaveModal(false)} + setIsOpen={setLeaveModal} isOpen={leaveModal} /> diff --git a/src/components/Room/Task.tsx b/src/components/Room/Task.tsx index 533e133..5e53f72 100644 --- a/src/components/Room/Task.tsx +++ b/src/components/Room/Task.tsx @@ -107,7 +107,7 @@ const RoomTask: React.FC = ({ task, room }) => { title='Delete Task' description='Are you sure you want to delete this task? This action cannot be undone.' proceed={taskDel} - dismiss={() => setDelModal(false)} + setIsOpen={setDelModal} isOpen={delModal} /> @@ -115,14 +115,14 @@ const RoomTask: React.FC = ({ task, room }) => { title='Visit URL' description={`Are you sure you want to go to this URL? ${task.url}`} href={task.url} - dismiss={() => setUrlModal(false)} + setIsOpen={setUrlModal} isOpen={urlModal} /> setOptionsModal(false)} + setIsOpen={setOptionsModal} body={

@@ -209,7 +209,7 @@ const RoomTask: React.FC = ({ task, room }) => { setDisplayImageModal(false)} + setIsOpen={() => setDisplayImageModal(false)} body={
{ }; return ( - +
{
-
+ ); }; diff --git a/src/components/RoomInput.tsx b/src/components/RoomInput.tsx new file mode 100644 index 0000000..9b2a54f --- /dev/null +++ b/src/components/RoomInput.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { IconType } from 'react-icons'; + +import { Header, Input } from '.'; +import { Button } from './Button'; + +interface RoomInputProps + extends Pick< + React.DetailedHTMLProps< + React.InputHTMLAttributes, + HTMLInputElement + >, + 'onChange' | 'value' | 'placeholder' + > { + title: string; + Icon: IconType; + btnLabel: string; + // eslint-disable-next-line no-unused-vars + onSubmit: (e: React.FormEvent) => void; +} + +const RoomInput = ({ + title, + Icon, + btnLabel, + onSubmit, + ...rest +}: RoomInputProps) => { + return ( + <> +
+
+ + +
+
+
+ + ); +}; + +export default RoomInput; diff --git a/src/components/index.ts b/src/components/index.ts index 06d963e..e0d4a3e 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -7,6 +7,7 @@ export { default as Header } from './Header'; export { default as Layout } from './Layout'; export { default as Loader } from './Loader'; export { default as EmptyMsg } from './EmptyMsg'; +export { default as RoomInput } from './RoomInput'; export { default as LoaderHandler } from './LoaderHandler'; -export { default as PendingContainer } from './PendingContainer'; +export { default as Confirmation } from './Confirmation'; export { default as UnderConstruction } from './UnderConstruction'; From e080a1f8ddb76b303a24e0b26450003846362d5e Mon Sep 17 00:00:00 2001 From: Josh Daniel Date: Wed, 2 Mar 2022 22:29:42 +0800 Subject: [PATCH 04/17] chore(deps): add prettier-plugin-tailwindcss --- package.json | 2 ++ yarn.lock | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/package.json b/package.json index 725108e..f34f8d3 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,8 @@ "husky": "^7.0.0", "lint-staged": "^12.3.2", "postcss": "^8.4.4", + "prettier": "^2.5.1", + "prettier-plugin-tailwindcss": "^0.1.8", "tailwindcss": "^3.0.1", "typescript": "4.4.3" }, diff --git a/yarn.lock b/yarn.lock index 8c54d96..dfce53d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2812,6 +2812,16 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier-plugin-tailwindcss@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.8.tgz#ba0f606ed91959ede670303d905b99106e9e6293" + integrity sha512-hwarSBCswAXa+kqYtaAkFr3Vop9o04WOyZs0qo3NyvW8L7f1rif61wRyq0+ArmVThOuRBcJF5hjGXYk86cwemg== + +prettier@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" + integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" From 98c649caed5cc79ca388aef80e14ce07f4c985b7 Mon Sep 17 00:00:00 2001 From: Josh Daniel Date: Thu, 3 Mar 2022 22:06:37 +0800 Subject: [PATCH 05/17] feat: add indicator for tasks status --- pages/room.tsx | 24 ++++++++------- src/components/Room/Task.tsx | 59 +++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/pages/room.tsx b/pages/room.tsx index 89967bb..57ef4ac 100644 --- a/pages/room.tsx +++ b/pages/room.tsx @@ -143,9 +143,9 @@ const Room = () => { e.preventDefault(); setModal(true); }} - className='w-full mt-4' + className='mt-4 w-full' > -
+
{ value={description} type='text' placeholder='Task Description' - className='bg-[#e5e5e5] h-[45px] outline-none w-full text-sm md:text-base' + className='h-[45px] w-full bg-[#e5e5e5] text-sm outline-none md:text-base' /> @@ -208,11 +208,13 @@ const Room = () => { } /> -
- {tasks?.map((task) => ( - - ))} -
+ {tasks && ( +
+ {tasks.map((task) => ( + + ))} +
+ )} ); }; diff --git a/src/components/Room/Task.tsx b/src/components/Room/Task.tsx index 5e53f72..1301410 100644 --- a/src/components/Room/Task.tsx +++ b/src/components/Room/Task.tsx @@ -96,13 +96,44 @@ const RoomTask: React.FC = ({ task, room }) => { }, ]; + const nearDeadline = () => { + const threeDaysFromNow = new Date(); + threeDaysFromNow.setDate(threeDaysFromNow.getDate() + 3); + + if (task.dueDate && task.dueDate.toDate() <= threeDaysFromNow) { + return true; + } + + return false; + }; + + const pastDeadline = () => { + const today = new Date(); + if (today > task.dueDate?.toDate()) { + return true; + } + + return false; + }; + + const displayIndicator = () => { + if (data.id && task.completedBy.includes(data.id)) return 'bg-green-500'; + if (pastDeadline()) return 'bg-red-500'; + if (nearDeadline()) return 'bg-secondary'; + return 'bg-gray-400'; + }; + return (
+
+ = ({ task, room }) => { isOpen={optionsModal} setIsOpen={setOptionsModal} body={ -
+

{taskInfo.map((val) => (

{val.title}:

{val.info}

@@ -150,7 +181,7 @@ const RoomTask: React.FC = ({ task, room }) => { }, 500); }} type='button' - className='bg-red-500 text-white modal-btn' + className='modal-btn bg-red-500 text-white' > Delete @@ -166,7 +197,7 @@ const RoomTask: React.FC = ({ task, room }) => { }, 500); }} type='button' - className='bg-amber-500 text-white modal-btn' + className='modal-btn bg-amber-500 text-white' > Go to URL @@ -175,7 +206,7 @@ const RoomTask: React.FC = ({ task, room }) => { @@ -185,16 +216,16 @@ const RoomTask: React.FC = ({ task, room }) => {
-

+

{task.description}

-
+

{task.dueDate ? dateWithTime(task.dueDate.toDate()) @@ -211,10 +242,10 @@ const RoomTask: React.FC = ({ task, room }) => { isOpen={displayImageModal} setIsOpen={() => setDisplayImageModal(false)} body={ -

+
task img
@@ -222,7 +253,7 @@ const RoomTask: React.FC = ({ task, room }) => { /> {task.imgUrls && task.imgUrls?.length > 0 && ( -
+
{task.imgUrls.map((url) => ( + } + /> + + +
+
+ +
+

{username}

+

{memberId}

+
+
+ + } + buttons={ +
+ {type !== 'creator' && ( + <> + + + + )} +
+ } + />
-
- {`${username} -
+

{username}

{type}

- {type === 'creator' ? ( - - ) : ( - - )} -
+
{Icon()}
+ ); }; diff --git a/src/components/Room/Task.tsx b/src/components/Room/Task.tsx index 3e9a2c6..2a00ef4 100644 --- a/src/components/Room/Task.tsx +++ b/src/components/Room/Task.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import Image from 'next/image'; import { nanoid } from 'nanoid'; import toast from 'react-hot-toast'; @@ -14,8 +14,9 @@ import { doc, updateDoc, } from 'firebase/firestore'; -import { dateWithTime } from '@/utils/functions'; +import { useUserByTag } from '@/services'; import { defaultPic } from '@/utils/constants'; +import { dateWithTime } from '@/utils/functions'; import { deleteObject, ref } from 'firebase/storage'; interface RoomTaskProps { @@ -31,23 +32,33 @@ const RoomTask: React.FC = ({ task, room }) => { const [displayImage, setDisplayImage] = useState(''); const [displayImageModal, setDisplayImageModal] = useState(false); - const { data } = useAuth(); - const isAdmin = room.creator === data.id; + const { + data: { userTag }, + } = useAuth(); const taskRef = doc(db, `rooms/${room?.id}/tasks/${task.id}`); - const completedByUser = task.completedBy.includes(data.id ?? ''); + const completedByUser = task.completedBy.includes(userTag ?? ''); + + const [taskCreator] = useUserByTag(task.addedBy); const hasImg = task.imgUrls && task.imgUrls?.length > 0; + const canDelete = useCallback(() => { + if (room.creator === userTag || room.admin.includes(userTag)) { + return true; + } + return task.addedBy === userTag; + }, [task, userTag]); + const taskDone = async () => { if (completedByUser) { await updateDoc(taskRef, { - completedBy: arrayRemove(data.id), + completedBy: arrayRemove(userTag), }); toast.success('Undo Successful'); } else { await updateDoc(taskRef, { - completedBy: arrayUnion(data.id), + completedBy: arrayUnion(userTag), }); toast.success('Task Completed'); @@ -84,11 +95,7 @@ const RoomTask: React.FC = ({ task, room }) => { }, { title: 'Added By', - info: task.addedBy, - }, - { - title: 'Completed By', - info: `${task.completedBy.length} member(s)`, + info: taskCreator.username, }, ]; @@ -113,8 +120,8 @@ const RoomTask: React.FC = ({ task, room }) => { }; const displayIndicator = () => { - if (data.id && task.completedBy.includes(data.id)) return 'bg-green-500'; - if (pastDeadline()) return 'bg-red-500'; + if (userTag && task.completedBy.includes(userTag)) return 'bg-green-600'; + if (pastDeadline()) return 'bg-red-600'; if (nearDeadline()) return 'bg-secondary'; return 'bg-gray-400'; }; @@ -131,9 +138,17 @@ const RoomTask: React.FC = ({ task, room }) => { + Delete + + } /> = ({ task, room }) => { } buttons={ <> - {isAdmin && ( + {canDelete() && ( @@ -200,7 +215,7 @@ const RoomTask: React.FC = ({ task, room }) => { diff --git a/src/services/index.ts b/src/services/index.ts index 9b75822..d878717 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,3 +1,4 @@ export { default as useRoom } from './useRoom'; export { default as useUser } from './useUser'; +export { default as useUserByTag } from './useUserByTag'; export { default as useCreatedRooms } from './useCreatedRooms'; diff --git a/src/services/useUserByTag.tsx b/src/services/useUserByTag.tsx new file mode 100644 index 0000000..660d4b3 --- /dev/null +++ b/src/services/useUserByTag.tsx @@ -0,0 +1,14 @@ +import { useCol } from '@/hooks'; +import { db } from '@/config/firebase'; +import { collection, query, where } from 'firebase/firestore'; + +const useUserByTag = (userTag: string) => { + const [_member, loading, error] = useCol( + query(collection(db, 'users'), where('userTag', '==', userTag)) + ); + + const member: IUser = _member ? _member[0] : ({} as IUser); + return [member, loading, error] as const; +}; + +export default useUserByTag; From c10e86f7b4dbc12ecf990b04209d2c2a5111b61b Mon Sep 17 00:00:00 2001 From: Josh Daniel Date: Sun, 6 Mar 2022 13:06:22 +0800 Subject: [PATCH 10/17] style: minor changes --- src/components/ImageFill.tsx | 2 +- src/components/Input.tsx | 2 +- src/components/Room/Info.tsx | 9 ++++++--- src/components/Room/RoomMenu.tsx | 10 +++++----- src/components/index.ts | 1 + 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/components/ImageFill.tsx b/src/components/ImageFill.tsx index 10a3a67..83a0061 100644 --- a/src/components/ImageFill.tsx +++ b/src/components/ImageFill.tsx @@ -11,7 +11,7 @@ const ImageFill = ({ src, className, ...rest }: ImageFillProps) => { return (
); diff --git a/src/components/Room/Info.tsx b/src/components/Room/Info.tsx index 368be14..ba43091 100644 --- a/src/components/Room/Info.tsx +++ b/src/components/Room/Info.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; - import { AiFillCalendar } from 'react-icons/ai'; import { IoMdKey } from 'react-icons/io'; import { useRouter } from 'next/router'; @@ -14,8 +13,8 @@ import { } from 'firebase/firestore'; import { useRoom } from '@/services'; -import { useNextQuery } from '@/hooks'; import { db } from '@/config/firebase'; +import { useNextQuery } from '@/hooks'; import { InfoBtn } from '@/components/Button'; import { useAuth } from '@/context/AuthContext'; import { Layout, Header, Error, Modal } from '@/components'; @@ -30,7 +29,7 @@ const Info: React.FC = () => { const id = useNextQuery('id'); const [room, loading] = useRoom(id); - const { creator, dateAdded, members } = room!; + const { creator, dateAdded, members, admin } = room!; const roomRef = doc(db, `rooms/${id}`); @@ -121,6 +120,10 @@ const Info: React.FC = () => {
+ {admin?.map((_admin) => ( + + ))} + {members?.map((member) => ( ))} diff --git a/src/components/Room/RoomMenu.tsx b/src/components/Room/RoomMenu.tsx index fb39b0e..321782d 100644 --- a/src/components/Room/RoomMenu.tsx +++ b/src/components/Room/RoomMenu.tsx @@ -14,10 +14,10 @@ const RoomMenu = ({ room }: { room: IRoom }) => { const { data } = useAuth(); return ( - + {() => ( <> - +

{room.name}

@@ -32,7 +32,7 @@ const RoomMenu = ({ room }: { room: IRoom }) => { leaveFrom='opacity-100 translate-y-0' leaveTo='opacity-0 translate-y-1' > - + {tab !== 'info' && ( )} @@ -44,12 +44,12 @@ const RoomMenu = ({ room }: { room: IRoom }) => { {tab && ( )} - {room.creator === data.id && tab !== 'requests' && ( + {room.creator === data.userTag && tab !== 'requests' && ( Date: Sun, 6 Mar 2022 15:23:44 +0800 Subject: [PATCH 11/17] chore: update limits --- pages/create.tsx | 6 ++++-- pages/join.tsx | 2 ++ src/components/Home/ListRooms.tsx | 6 ++++-- src/components/Home/MyRooms.tsx | 2 +- src/components/Room/Info.tsx | 10 +++++++++- src/components/Room/Task.tsx | 3 ++- src/components/RoomInput.tsx | 10 +++++----- 7 files changed, 27 insertions(+), 12 deletions(-) diff --git a/pages/create.tsx b/pages/create.tsx index 0bd03f4..851c9ba 100644 --- a/pages/create.tsx +++ b/pages/create.tsx @@ -36,8 +36,8 @@ const Create: NextPageWithLayout = () => { }; setRoomName(''); - if (roomsCreated && roomsCreated.length >= 3) { - toast.error('max rooms reached (3)'); + if (roomsCreated && roomsCreated.length >= 5) { + toast.error('max rooms reached (5)'); } else if (roomName) { toast.promise(setDoc(doc(db, 'rooms', roomId), payload), { loading: 'Creating Room...', @@ -58,6 +58,8 @@ const Create: NextPageWithLayout = () => { onChange={(e) => setRoomName(e.target.value)} value={roomName} placeholder='enter room name' + minLength={3} + maxLength={25} /> ); }; diff --git a/pages/join.tsx b/pages/join.tsx index 7783eb7..24054f3 100644 --- a/pages/join.tsx +++ b/pages/join.tsx @@ -56,6 +56,8 @@ const Join: NextPageWithLayout = () => { onChange={(e) => setRoomID(e.target.value)} value={roomId} placeholder='enter room id' + minLength={5} + maxLength={15} /> ); }; diff --git a/src/components/Home/ListRooms.tsx b/src/components/Home/ListRooms.tsx index 68c18ad..d6ae8ba 100644 --- a/src/components/Home/ListRooms.tsx +++ b/src/components/Home/ListRooms.tsx @@ -13,11 +13,13 @@ const ListRooms: React.FC = ({ room }) => { + } /> = ({ task, room }) => { : 'No Due Date'}

- Done: {task.completedBy?.length}/{room?.members?.length + 1} + Done: {task.completedBy?.length}/ + {room?.members?.length + 1 + room.admin.length}

diff --git a/src/components/RoomInput.tsx b/src/components/RoomInput.tsx index 9b2a54f..0977a63 100644 --- a/src/components/RoomInput.tsx +++ b/src/components/RoomInput.tsx @@ -5,12 +5,12 @@ import { Header, Input } from '.'; import { Button } from './Button'; interface RoomInputProps - extends Pick< + extends Omit< React.DetailedHTMLProps< React.InputHTMLAttributes, HTMLInputElement >, - 'onChange' | 'value' | 'placeholder' + 'onSubmit' > { title: string; Icon: IconType; @@ -31,11 +31,11 @@ const RoomInput = ({
- + -
+
- + ); }; diff --git a/src/components/Room/InfoMember.tsx b/src/components/Room/InfoMember.tsx index 810b0ac..c4ac4cf 100644 --- a/src/components/Room/InfoMember.tsx +++ b/src/components/Room/InfoMember.tsx @@ -41,13 +41,15 @@ const InfoMember = ({ memberId, type }: InfoSectionProps) => { setUserModal(false); setTimeout(async () => { - await updateDoc(roomRef, { - admin: isAdmin ? arrayRemove(memberId) : arrayUnion(memberId), - }); + await Promise.all([ + updateDoc(roomRef, { + members: isAdmin ? arrayUnion(memberId) : arrayRemove(memberId), + }), - await updateDoc(roomRef, { - members: isAdmin ? arrayUnion(memberId) : arrayRemove(memberId), - }); + updateDoc(roomRef, { + admin: isAdmin ? arrayRemove(memberId) : arrayUnion(memberId), + }), + ]); toast.success(`${username} is ${isAdmin ? 'no longer' : 'now'} an admin`); }, 500); @@ -70,9 +72,7 @@ const InfoMember = ({ memberId, type }: InfoSectionProps) => { return (
- + ); }; diff --git a/src/components/Room/Requests.tsx b/src/components/Room/Requests.tsx index c61b1c5..acbb95c 100644 --- a/src/components/Room/Requests.tsx +++ b/src/components/Room/Requests.tsx @@ -3,14 +3,14 @@ import React from 'react'; import { useRoom } from '@/services'; import { useNextQuery } from '@/hooks'; import { RoomMenu, UserRequest } from '.'; -import { Layout, Header, EmptyMsg } from '@/components'; +import { Header, EmptyMsg } from '@/components'; const Requests = () => { const id = useNextQuery('id'); - const [room, loading] = useRoom(id); + const [room] = useRoom(id); return ( - + <>
{!room?.requests?.length && } @@ -19,7 +19,7 @@ const Requests = () => { ))}
- + ); }; From bcd005898a72fe3a4c0a9c807a01f7b3c6a025ca Mon Sep 17 00:00:00 2001 From: Josh Daniel Date: Sun, 6 Mar 2022 15:41:02 +0800 Subject: [PATCH 13/17] refactor: rename to contexts --- pages/_app.tsx | 2 +- pages/create.tsx | 2 +- pages/home.tsx | 2 +- pages/index.tsx | 28 +++++++++++------------ pages/invites.tsx | 2 +- pages/join.tsx | 2 +- pages/room.tsx | 2 +- src/components/Layout.tsx | 4 ++-- src/components/LoaderHandler.tsx | 8 +++---- src/components/Nav/NavMenu.tsx | 6 ++--- src/components/Navbar.tsx | 18 +++++++-------- src/components/Room/Info.tsx | 2 +- src/components/Room/InviteUser.tsx | 2 +- src/components/Room/RoomMenu.tsx | 2 +- src/components/Room/Task.tsx | 2 +- src/{context => contexts}/AuthContext.tsx | 0 16 files changed, 42 insertions(+), 42 deletions(-) rename src/{context => contexts}/AuthContext.tsx (100%) diff --git a/pages/_app.tsx b/pages/_app.tsx index 6c31e9d..9cb8716 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -8,7 +8,7 @@ import NProgress from 'nprogress'; import { DefaultSeo } from 'next-seo'; import { Toaster } from 'react-hot-toast'; import { AppPropsWithLayout } from '@/types/page'; -import { AuthProvider } from '@/context/AuthContext'; +import { AuthProvider } from '@/contexts/AuthContext'; import SEO from '../next-seo-config'; diff --git a/pages/create.tsx b/pages/create.tsx index 851c9ba..4e1174c 100644 --- a/pages/create.tsx +++ b/pages/create.tsx @@ -8,7 +8,7 @@ import { doc, setDoc, serverTimestamp } from 'firebase/firestore'; import { db } from '@/config/firebase'; import { useCreatedRooms } from '@/services'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; import { Layout, RoomInput } from '@/components'; import { NextPageWithLayout } from '@/types/page'; diff --git a/pages/home.tsx b/pages/home.tsx index 95ffc3a..0a121fd 100644 --- a/pages/home.tsx +++ b/pages/home.tsx @@ -14,7 +14,7 @@ import { MyRooms } from '@/components/Home'; import { defaultPic } from '@/utils/constants'; import { Button } from '@/components/Button'; import { useCreatedRooms } from '@/services'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; const Homepage: React.FC = () => { const { push } = useRouter(); diff --git a/pages/index.tsx b/pages/index.tsx index b4a8330..f0893a8 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -7,7 +7,7 @@ import { FaSignInAlt } from 'react-icons/fa'; import { Layout } from '@/components'; import avatar from '@/assets/avatar.svg'; import { Button } from '@/components/Button'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; import { landingPage } from '@/utils/constants'; import { NextPageWithLayout } from '@/types/page'; @@ -17,16 +17,16 @@ const Index: NextPageWithLayout = () => { return ( <> -
-
-

+
+
+

trackAs One

-
+
-
+
{ />
-

+

A collaborative task tracker.

-

+

{landingPage.body1}

@@ -53,13 +53,13 @@ const Index: NextPageWithLayout = () => {
-
+
trackAsOne avatar
-
-
    +
    +
      {['User-Friendly', 'Collaborative', 'Open-Source'].map((i) => (
    • {i}

      @@ -68,7 +68,7 @@ const Index: NextPageWithLayout = () => {
    -
    +
    { return (
    -

    +

    {title}

    -

    +

    {body}

    diff --git a/pages/invites.tsx b/pages/invites.tsx index 8acb99e..0665e19 100644 --- a/pages/invites.tsx +++ b/pages/invites.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useUser } from '@/services'; import { Invitation } from '@/components/Home'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; import { Layout, Header, EmptyMsg } from '@/components'; const Invites: React.FC = () => { diff --git a/pages/join.tsx b/pages/join.tsx index 24054f3..911f92d 100644 --- a/pages/join.tsx +++ b/pages/join.tsx @@ -7,7 +7,7 @@ import { arrayUnion, doc, getDoc, updateDoc } from 'firebase/firestore'; import { db } from '@/config/firebase'; import Layout from '@/components/Layout'; import { RoomInput } from '@/components'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; import { NextPageWithLayout } from '@/types/page'; const Join: NextPageWithLayout = () => { diff --git a/pages/room.tsx b/pages/room.tsx index b8347d1..446c58c 100644 --- a/pages/room.tsx +++ b/pages/room.tsx @@ -24,7 +24,7 @@ import { import { useRoom } from '@/services'; import { db } from '@/config/firebase'; import { urlRegExp } from '@/utils/constants'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; import { NextPageWithLayout } from '@/types/page'; import { Layout, Error, Modal } from '@/components'; import { useCol, useNextQuery, useUpload } from '@/hooks'; diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index ec82b1c..64cb33e 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { NextSeo, NextSeoProps } from 'next-seo'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; import { Navbar, Footer, LoaderHandler, Error } from '@/components'; interface LayoutProps extends NextSeoProps { @@ -33,7 +33,7 @@ const Layout: React.FC = ({
    diff --git a/src/components/LoaderHandler.tsx b/src/components/LoaderHandler.tsx index 375ae99..9b3a69d 100644 --- a/src/components/LoaderHandler.tsx +++ b/src/components/LoaderHandler.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; import { Loader } from '.'; @@ -23,9 +23,9 @@ const LoaderHandler: React.FC = ({ loaders, children }) => { if (loading || _loading()) { return ( -
    - -
    +
    + +
    ); } diff --git a/src/components/Nav/NavMenu.tsx b/src/components/Nav/NavMenu.tsx index 8b9b8d5..7af7bfe 100644 --- a/src/components/Nav/NavMenu.tsx +++ b/src/components/Nav/NavMenu.tsx @@ -3,7 +3,7 @@ import { Popover, Transition } from '@headlessui/react'; import { MenuBtn } from '@/components/Button'; import { AiFillContacts, AiFillHome, AiFillInfoCircle } from 'react-icons/ai'; -import { useAuth } from '@/context/AuthContext'; +import { useAuth } from '@/contexts/AuthContext'; const NavMenu = () => { const { user } = useAuth(); @@ -12,7 +12,7 @@ const NavMenu = () => { {() => ( <> - + Menu @@ -25,7 +25,7 @@ const NavMenu = () => { leaveFrom='opacity-100 translate-y-0' leaveTo='opacity-0 translate-y-1' > - + { const { user, signIn, signOut } = useAuth(); @@ -17,26 +17,26 @@ const Navbar: React.FC = () => { return (