Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPK-257-Add-a-store-for-Dashboard-Data #69

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 6 additions & 39 deletions src/app/dashboard/bookings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,45 +41,14 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
import { Calendar } from "@/components/ui/calendar";
import { useDashboardData } from "@/components/dashboard/DashboardContext";
import { type Appointment, type Company } from "@/types";
import { useSelector } from "react-redux";
import { type RootState } from "@/store/store";

function Bookings() {
const { user } = useDashboardData();
const [searchQuery, setSearchQuery] = useState("");
const [appointments, setAppointments] = useState<Appointment[]>([
{
id: 1,
from: new Date(2024, 8, 3, 18, 30),
to: new Date(2024, 8, 3, 19, 30),
title: "Scrum Meeting",
description: "Weekly team sync",
companyId: "1",
location: "Office",
client: null,
status: "PENDING"
},
{
id: 2,
from: new Date(2024, 8, 5, 17, 30),
to: new Date(2024, 8, 5, 18, 30),
title: "Client Presentation",
description: "Presenting project progress",
companyId: "2",
location: "Conference Room",
client: null,
status: "BOOKED"
},
{
id: 3,
from: new Date(2024, 8, 6, 21, 30),
to: new Date(2024, 8, 6, 22, 30),
title: "Client Presentation",
description: "Presenting project progress",
companyId: "2",
location: "Conference Room",
client: null,
status: "BOOKED"
}
]);
const appointments = useSelector((state: RootState) => state.collection.appointments);

const [companies, setCompanies] = useState<Company[]>([
{
id: "1",
Expand All @@ -99,11 +68,9 @@ function Bookings() {
}
}
}
// Add more companies as needed
]);

useEffect(() => {
if (false) setAppointments([]);
if (false) setCompanies([]);
}, []);

Expand Down Expand Up @@ -186,8 +153,8 @@ function Bookings() {
}

// Find the earliest start time and latest end time
const earliestTime = Math.min(...calcAppointments.map((a) => a.from.getHours()));
const latestTime = Math.max(...calcAppointments.map((a) => a.to.getHours()));
const earliestTime = Math.min(...calcAppointments.map((a) => new Date(a.from).getHours()));
const latestTime = Math.max(...calcAppointments.map((a) => new Date(a.to).getHours()));

let startHour: number;
let endHour: number;
Expand Down
2 changes: 1 addition & 1 deletion src/app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
<div
className="absolute mt-10 flex h-16 w-[80px] items-center justify-start rounded-l-md bg-subtle shadow-lg"
style={{ marginTop: companyIndicatorTop }}>
<div className="ml-[8px] h-[50%] w-px bg-primary"></div>
<div className="ml-[8px] h-1/2 w-px bg-primary"></div>
</div>
<div className="mt-12 size-12 rounded-md">
<Link href={"/dashboard"}>
Expand Down
73 changes: 22 additions & 51 deletions src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import React, { useEffect, useState } from "react";
import { deleteToken, getAccessToken, getUser } from "@/lib/authActions";
Expand All @@ -19,52 +18,16 @@ import { useRouter } from "next/navigation";
import Link from "next/link";
import OverviewScheduler from "@/components/dashboard/scheduler/OverviewScheduler";
import AppointmentDisplay from "@/components/dashboard/AppointmentDisplay";
import { useSelector } from "react-redux";
import type { RootState } from "@/store/store";

function Dashboard() {
const [user, setUser] = useState<User | null>();
const [loading, setLoading] = useState(true);

const router = useRouter();

const [appointments, setAppointments] = useState<Appointment[]>([
{
id: 1,
from: new Date(2024, 8, 23, 18, 30),
to: new Date(2024, 8, 23, 19, 30),
title: "Scrum Meeting",
description: "Weekly team sync",
companyId: "1",
location: "Office",
client: null,
status: "PENDING"
},
{
id: 2,
from: new Date(2024, 8, 25, 17, 30),
to: new Date(2024, 8, 25, 18, 30),
title: "Client Presentation",
description: "Presenting project progress",
companyId: "2",
location: "Conference Room",
client: null,
status: "BOOKED"
},
{
id: 3,
from: new Date(2024, 8, 25, 21, 30),
to: new Date(2024, 8, 25, 22, 30),
title: "Client Presentation",
description: "Presenting project progress",
companyId: "2",
location: "Conference Room",
client: null,
status: "BOOKED"
}
]);

useEffect(() => {
if (false) setAppointments([]);
}, []);
const appointments = useSelector((state: RootState) => state.collection.appointments);

useEffect(() => {
const fetchUser = async () => {
Expand Down Expand Up @@ -112,7 +75,6 @@ function Dashboard() {
<header className="flex w-full flex-row items-center justify-between">
<h1 className="m-4 font-medium text-muted-foreground md:text-2xl">Welcome back, {user?.name}</h1>
<div className="flex items-center gap-x-6">
<Input className="w-[320px]" placeholder="Search"></Input>
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild className={"mr-4"}>
<Button variant="ghost" className="relative size-8 rounded-full">
Expand Down Expand Up @@ -157,18 +119,27 @@ function Dashboard() {
<div className="mt-8 flex h-fit w-full rounded-[20px] bg-subtle py-4">
<div className="flex flex-col items-center justify-start gap-4 p-8">
<h2 className="text-2xl font-semibold">Upcoming Appointments</h2>
<div className="mt-2 flex max-h-[500px] flex-col items-start justify-start gap-y-6 overflow-scroll">
{appointments.map((appointment) => (
<AppointmentDisplay
onClick={handleAppointmentClick}
key={appointment.id}
data={appointment}
selected={appointment.id === selectedAppointmentId}
/>
))}
<div className="mt-2 flex max-h-[500px] flex-col items-start justify-start gap-y-6 overflow-y-auto overflow-x-hidden">
{appointments.length !== 0 ? (
appointments.map((appointment) => (
<AppointmentDisplay
onClick={handleAppointmentClick}
key={appointment.id}
data={appointment}
selected={appointment.id === selectedAppointmentId}
/>
))
) : (
<p className={"min-w-80 text-center text-muted-foreground"}>
You have no upcoming appointments. <br />
<Button variant={"secondary"} className="mt-2">
<Link href={"/dashboard/bookings"}>Book now</Link>
</Button>
</p>
)}
</div>
</div>
<div className="items-center-justify-start flex flex-col gap-4 p-8">
<div className="items-center-justify-start flex max-w-3xl flex-col gap-4 p-8">
<h2 className="text-2xl font-semibold">Timeline</h2>
<OverviewScheduler data={appointments} selectedAppointmentId={selectedAppointmentId} />
</div>
Expand Down
8 changes: 5 additions & 3 deletions src/components/dashboard/AppointmentDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ export default function AppointmentDisplay(props: {
<div
className={`flex size-[100px] flex-col items-center justify-center rounded-2xl text-white ${!props.selected && "bg-secondary"}`}>
<p className={`text-xl ${!props.selected && "text-muted-foreground"}`}>
{props.data.from.toLocaleString("en-US", { weekday: "short" })}
{new Date(props.data.from).toLocaleString("en-US", { weekday: "short" })}
</p>
<p className={`text-2xl font-bold ${!props.selected && "text-primary"}`}>
{new Date(props.data.from).getDate()}
</p>
<p className={`text-2xl font-bold ${!props.selected && "text-primary"}`}>{props.data.from.getDate()}</p>
</div>
<div className={`flex flex-col items-start justify-start`}>
<p className="text-xl font-medium">{props.data.title}</p>
<p className="mb-1 text-base text-[#dddddd]">{"GitHub Company"}</p> {/* Get Company by ID here */}
<div
className={`flex flex-col items-start justify-start rounded-lg px-2 py-1 text-sm text-primary ${props.selected ? "bg-white" : "bg-elevated"}`}>
{props.data.from.getHours()}:{props.data.from.getMinutes()}
{new Date(props.data.from).getHours()}:{new Date(props.data.from).getMinutes()}
</div>
</div>
</div>
Expand Down
13 changes: 8 additions & 5 deletions src/components/dashboard/scheduler/OverviewScheduler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "./scheduler.scss";
import "./overviewscheduler.scss";
import { registerLicense } from "@syncfusion/ej2-base";
import { type Appointment } from "@/types";
import { useRouter } from "next/navigation";

type SchedulerProps = {
data: Appointment[];
Expand All @@ -23,11 +24,12 @@ function OverviewScheduler(props: SchedulerProps) {
const eventSettings = { dataSource: props.data, fields: fieldsData };

const predefinedColors = ["#6EE7B7", "#F87171", "#FACC15"];
const router = useRouter();

registerLicense(process.env.NEXT_PUBLIC_SYNCFUSION_LICENSE!);

const onEventClick = (args: { cancel: boolean }) => {
console.log("Event clicked", args);
router.push("/dashboard/bookings");
args.cancel = true;
};

Expand All @@ -44,8 +46,8 @@ function OverviewScheduler(props: SchedulerProps) {
}

// Find the earliest start time and latest end time
const earliestTime = Math.min(...calcAppointments.map((a) => a.from.getHours()));
const latestTime = Math.max(...calcAppointments.map((a) => a.to.getHours()));
const earliestTime = Math.min(...calcAppointments.map((a) => new Date(a.from).getHours()));
const latestTime = Math.max(...calcAppointments.map((a) => new Date(a.to).getHours()));

let startHour: number;
let endHour: number;
Expand Down Expand Up @@ -99,6 +101,7 @@ function OverviewScheduler(props: SchedulerProps) {
height={"500px"}
eventSettings={eventSettings}
showHeaderBar={false}
showTimeIndicator={false}
eventRendered={onEventRendered}
key={props.selectedAppointmentId}
readonly={true}
Expand All @@ -111,9 +114,9 @@ function OverviewScheduler(props: SchedulerProps) {
eventTemplate={(eventProps: Record<string, unknown>) => {
return (
<div
className={`z-10 size-full rounded-[12px] border-primary`}
className={`z-10 size-full cursor-pointer rounded-[12px] border-primary`}
style={{
borderWidth: eventProps.id === props.selectedAppointmentId ? "2px" : "0"
borderWidth: eventProps.id === props.selectedAppointmentId ? "4px" : "0"
}}></div>
);
}}
Expand Down
63 changes: 63 additions & 0 deletions src/store/features/collectionSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { type Appointment, type Company } from "@/types";
import { createSlice, type PayloadAction } from "@reduxjs/toolkit";

type CollectionState = {
appointments: Appointment[];
companies: Company[];
};

const initialState: CollectionState = {
appointments: [
{
id: 1,
from: new Date(2024, 8, 23, 18, 30),
to: new Date(2024, 8, 23, 19, 30),
title: "Scrum Meeting",
description: "Weekly team sync",
companyId: "1",
location: "Office",
client: null,
status: "PENDING"
},
{
id: 2,
from: new Date(2024, 8, 25, 17, 30),
to: new Date(2024, 8, 25, 18, 30),
title: "Client Presentation",
description: "Presenting project progress",
companyId: "2",
location: "Conference Room",
client: null,
status: "BOOKED"
},
{
id: 3,
from: new Date(2024, 8, 25, 21, 30),
to: new Date(2024, 8, 25, 22, 30),
title: "Client Presentation",
description: "Presenting project progress",
companyId: "2",
location: "Conference Room",
client: null,
status: "BOOKED"
}
],
companies: []
};

export const collectionSlice = createSlice({
name: "appointments",
initialState,
reducers: {
setAppointments(state, action: PayloadAction<Appointment[]>) {
state.appointments = action.payload;
},
setCompanies(state, action: PayloadAction<Company[]>) {
state.companies = action.payload;
}
}
});

export const { setAppointments, setCompanies } = collectionSlice.actions;

export default collectionSlice.reducer;
4 changes: 3 additions & 1 deletion src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { persistReducer, persistStore } from "redux-persist";
import storage from "redux-persist/lib/storage";
import authReducer from "./features/authSlice";
import cookieReducer from "./features/cookieSlice";
import collectionReducer from "./features/collectionSlice";

const rootReducer = combineReducers({
auth: authReducer,
cookie: cookieReducer
cookie: cookieReducer,
collection: collectionReducer
});

const persistConfig = {
Expand Down