From 8cca1fd99d2771cd5b193324743ae943e9c58574 Mon Sep 17 00:00:00 2001
From: Spencer Schoeneman <78219375+Spencer-Sch@users.noreply.github.com>
Date: Fri, 1 Dec 2023 15:05:00 -0600
Subject: [PATCH] Add DashWind dashboard (#5)
* edit form submit buttons width
* add reduxToolkit, react-redux, next redux wrapper packages
* add dash-wind components converted to typescript
* change all Next back to HTML
* edit store.ts to follow next-redux-wrapper docs
* add next-redux-wrapper provider to _app.tsx
* move to store.ts
* swap out react-redux imports for next-react-redux imports
* move FormSteps type to its own ts file
* add login/register/forgot-password/welcome pages and edit link routing
* small edits
* add deps to useEffect deps array
* add page layout for dashboard with header and side nav
* add 404 fallback page
* backup original dapp onboarding flow - probably delete later
* remove some commented code
* routing and icon edit
* edit routes, comment out some sidebar routs, rename 404 page so it will work
* edit route
* add all dashboard pages
* add all missing deps to useEffect deps arrays
* add more deps to deps arrays
* es-lint ignore img elements
---
packages/nextjs/components/Header.tsx | 5 +-
.../nextjs/components/dash-wind/app/auth.ts | 43 +++
.../nextjs/components/dash-wind/app/init.ts | 20 ++
.../nextjs/components/dash-wind/app/store.ts | 62 ++++
.../components/CalendarView/index.tsx | 178 +++++++++++
.../dash-wind/components/CalendarView/util.ts | 29 ++
.../dash-wind/components/Cards/TitleCard.tsx | 30 ++
.../dash-wind/components/Input/InputText.tsx | 51 ++++
.../dash-wind/components/Input/SearchBar.tsx | 30 ++
.../dash-wind/components/Input/SelectBox.tsx | 77 +++++
.../components/Input/TextAreaInput.tsx | 46 +++
.../components/Input/ToggleInput.tsx | 44 +++
.../components/Typography/ErrorText.tsx | 12 +
.../components/Typography/HelperText.tsx | 12 +
.../components/Typography/Subtitle.tsx | 11 +
.../dash-wind/components/Typography/Title.tsx | 13 +
.../dash-wind/containers/Header.tsx | 127 ++++++++
.../dash-wind/containers/Layout.tsx | 55 ++++
.../dash-wind/containers/LeftSidebar.tsx | 62 ++++
.../dash-wind/containers/ModalLayout.tsx | 45 +++
.../dash-wind/containers/PageContent.tsx | 36 +++
.../dash-wind/containers/RightSidebar.tsx | 68 +++++
.../dash-wind/containers/SidebarSubmenu.tsx | 70 +++++
.../dash-wind/containers/SuspenseContent.tsx | 5 +
.../CalendarEventsBodyRightDrawer.tsx | 23 ++
.../dash-wind/features/calendar/index.tsx | 46 +++
.../features/charts/components/BarChart.tsx | 46 +++
.../charts/components/DoughnutChart.tsx | 54 ++++
.../features/charts/components/LineChart.tsx | 51 ++++
.../features/charts/components/PieChart.tsx | 54 ++++
.../charts/components/ScatterChart.tsx | 44 +++
.../charts/components/StackBarChart.tsx | 56 ++++
.../dash-wind/features/charts/index.tsx | 57 ++++
.../components/ConfirmationModalBody.tsx | 44 +++
.../NotificationBodyRightDrawer.tsx | 20 ++
.../dash-wind/features/common/headerSlice.ts | 45 +++
.../dash-wind/features/common/modalSlice.ts | 51 ++++
.../features/common/rightDrawerSlice.ts | 47 +++
.../dashboard/components/AmountStats.tsx | 23 ++
.../dashboard/components/BarChart.tsx | 46 +++
.../dashboard/components/DashboardStats.tsx | 29 ++
.../dashboard/components/DashboardTopBar.tsx | 97 ++++++
.../dashboard/components/DoughnutChart.tsx | 54 ++++
.../dashboard/components/LineChart.tsx | 51 ++++
.../dashboard/components/PageStats.tsx | 28 ++
.../dashboard/components/UserChannels.tsx | 43 +++
.../dash-wind/features/dashboard/index.tsx | 80 +++++
.../dash-wind/features/integration/index.tsx | 102 +++++++
.../leads/components/AddLeadModalBody.tsx | 90 ++++++
.../dash-wind/features/leads/index.tsx | 116 +++++++
.../dash-wind/features/leads/leadSlice.ts | 74 +++++
.../features/settings/billing/index.tsx | 156 ++++++++++
.../settings/profilesettings/index.tsx | 60 ++++
.../features/settings/team/index.tsx | 145 +++++++++
.../dash-wind/features/transactions/index.tsx | 149 +++++++++
.../features/user/ForgotPassword.tsx | 100 +++++++
.../dash-wind/features/user/LandingIntro.tsx | 27 ++
.../dash-wind/features/user/Login.tsx | 97 ++++++
.../dash-wind/features/user/Register.tsx | 98 ++++++
.../user/components/TemplatePointers.tsx | 25 ++
.../dash-wind/pages/DocComponents.js | 11 +
.../dash-wind/pages/DocFeatures.tsx | 11 +
.../dash-wind/pages/Documentation.js | 40 +++
.../dash-wind/pages/ForgotPassword.tsx | 11 +
.../dash-wind/pages/GettingStarted.js | 12 +
.../components/dash-wind/pages/Login.tsx | 11 +
.../components/dash-wind/pages/Register.tsx | 11 +
.../dash-wind/pages/protected/Bills.tsx | 16 +
.../dash-wind/pages/protected/Blank.tsx | 25 ++
.../dash-wind/pages/protected/Calendar.tsx | 16 +
.../dash-wind/pages/protected/Charts.tsx | 16 +
.../dash-wind/pages/protected/Dashboard.tsx | 16 +
.../dash-wind/pages/protected/Integration.tsx | 16 +
.../dash-wind/pages/protected/Leads.tsx | 16 +
.../pages/protected/ProfileSettings.tsx | 16 +
.../dash-wind/pages/protected/Team.tsx | 16 +
.../pages/protected/Transactions.tsx | 16 +
.../dash-wind/pages/protected/Welcome.tsx | 28 ++
.../dash-wind/pages/protected/_404.tsx | 25 ++
.../components/dash-wind/routes/index.ts | 83 ++++++
.../components/dash-wind/routes/sidebar.ts | 155 ++++++++++
.../dash-wind/types/CalendarTypes.ts | 18 ++
.../components/dash-wind/types/DateTypes.ts | 6 +
.../components/dash-wind/types/FormTypes.ts | 4 +
.../dash-wind/types/InputTextTypes.ts | 20 ++
.../dash-wind/types/declarations.d.ts | 1 +
.../components/dash-wind/utils/dummyData.ts | 227 ++++++++++++++
.../dash-wind/utils/globalConstantUtil.ts | 16 +
.../nextjs/components/layouts/DashLayout.tsx | 49 +++
.../web-3-crew/ExistingOrNewMember.tsx | 2 +-
.../web-3-crew/LoginEmailOrWallet.tsx | 2 +-
.../web-3-crew/RegisterCompanyOrEmployee.tsx | 2 +-
.../web-3-crew/buttons/BackButton.tsx | 2 +-
.../web-3-crew/forms/RegisterCompanyForm.tsx | 4 +-
.../web-3-crew/forms/RegisterEmployeeForm.tsx | 4 +-
.../components/web-3-crew/types/FormSteps.ts | 1 +
packages/nextjs/package.json | 11 +
packages/nextjs/pages/404.tsx | 9 +
packages/nextjs/pages/_app.tsx | 11 +-
packages/nextjs/pages/dapp/404.tsx | 19 ++
packages/nextjs/pages/dapp/blank.tsx | 19 ++
packages/nextjs/pages/dapp/calendar.tsx | 19 ++
packages/nextjs/pages/dapp/charts.tsx | 19 ++
packages/nextjs/pages/dapp/dashboard.tsx | 19 ++
packages/nextjs/pages/dapp/integration.tsx | 19 ++
packages/nextjs/pages/dapp/leads.tsx | 19 ++
.../nextjs/pages/dapp/settings-billing.tsx | 19 ++
.../nextjs/pages/dapp/settings-profile.tsx | 19 ++
packages/nextjs/pages/dapp/settings-team.tsx | 19 ++
packages/nextjs/pages/dapp/transactions.tsx | 19 ++
packages/nextjs/pages/dapp/welcome.tsx | 20 ++
packages/nextjs/pages/forgot-password.tsx | 20 ++
packages/nextjs/pages/index.tsx | 2 +-
packages/nextjs/pages/login.tsx | 20 ++
.../nextjs/pages/{dapp.tsx => orig_dapp.tsx} | 3 +-
packages/nextjs/pages/register.tsx | 20 ++
packages/nextjs/tailwind.config.js | 7 +-
packages/nextjs/tsconfig.json | 5 +-
yarn.lock | 282 +++++++++++++++++-
119 files changed, 4983 insertions(+), 20 deletions(-)
create mode 100644 packages/nextjs/components/dash-wind/app/auth.ts
create mode 100644 packages/nextjs/components/dash-wind/app/init.ts
create mode 100644 packages/nextjs/components/dash-wind/app/store.ts
create mode 100644 packages/nextjs/components/dash-wind/components/CalendarView/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/CalendarView/util.ts
create mode 100644 packages/nextjs/components/dash-wind/components/Cards/TitleCard.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Input/InputText.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Input/SearchBar.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Input/SelectBox.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Input/TextAreaInput.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Input/ToggleInput.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Typography/ErrorText.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Typography/HelperText.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Typography/Subtitle.tsx
create mode 100644 packages/nextjs/components/dash-wind/components/Typography/Title.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/Header.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/Layout.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/LeftSidebar.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/ModalLayout.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/PageContent.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/RightSidebar.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/SidebarSubmenu.tsx
create mode 100644 packages/nextjs/components/dash-wind/containers/SuspenseContent.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/calendar/CalendarEventsBodyRightDrawer.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/calendar/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/charts/components/BarChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/charts/components/DoughnutChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/charts/components/LineChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/charts/components/PieChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/charts/components/ScatterChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/charts/components/StackBarChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/charts/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/common/components/ConfirmationModalBody.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/common/components/NotificationBodyRightDrawer.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/common/headerSlice.ts
create mode 100644 packages/nextjs/components/dash-wind/features/common/modalSlice.ts
create mode 100644 packages/nextjs/components/dash-wind/features/common/rightDrawerSlice.ts
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/AmountStats.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/BarChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/DashboardStats.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/DashboardTopBar.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/DoughnutChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/LineChart.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/PageStats.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/components/UserChannels.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/dashboard/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/integration/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/leads/components/AddLeadModalBody.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/leads/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/leads/leadSlice.ts
create mode 100644 packages/nextjs/components/dash-wind/features/settings/billing/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/settings/profilesettings/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/settings/team/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/transactions/index.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/user/ForgotPassword.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/user/LandingIntro.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/user/Login.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/user/Register.tsx
create mode 100644 packages/nextjs/components/dash-wind/features/user/components/TemplatePointers.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/DocComponents.js
create mode 100644 packages/nextjs/components/dash-wind/pages/DocFeatures.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/Documentation.js
create mode 100644 packages/nextjs/components/dash-wind/pages/ForgotPassword.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/GettingStarted.js
create mode 100644 packages/nextjs/components/dash-wind/pages/Login.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/Register.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Bills.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Blank.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Calendar.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Charts.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Dashboard.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Integration.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Leads.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/ProfileSettings.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Team.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Transactions.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/Welcome.tsx
create mode 100644 packages/nextjs/components/dash-wind/pages/protected/_404.tsx
create mode 100644 packages/nextjs/components/dash-wind/routes/index.ts
create mode 100644 packages/nextjs/components/dash-wind/routes/sidebar.ts
create mode 100644 packages/nextjs/components/dash-wind/types/CalendarTypes.ts
create mode 100644 packages/nextjs/components/dash-wind/types/DateTypes.ts
create mode 100644 packages/nextjs/components/dash-wind/types/FormTypes.ts
create mode 100644 packages/nextjs/components/dash-wind/types/InputTextTypes.ts
create mode 100644 packages/nextjs/components/dash-wind/types/declarations.d.ts
create mode 100644 packages/nextjs/components/dash-wind/utils/dummyData.ts
create mode 100644 packages/nextjs/components/dash-wind/utils/globalConstantUtil.ts
create mode 100644 packages/nextjs/components/layouts/DashLayout.tsx
create mode 100644 packages/nextjs/components/web-3-crew/types/FormSteps.ts
create mode 100644 packages/nextjs/pages/404.tsx
create mode 100644 packages/nextjs/pages/dapp/404.tsx
create mode 100644 packages/nextjs/pages/dapp/blank.tsx
create mode 100644 packages/nextjs/pages/dapp/calendar.tsx
create mode 100644 packages/nextjs/pages/dapp/charts.tsx
create mode 100644 packages/nextjs/pages/dapp/dashboard.tsx
create mode 100644 packages/nextjs/pages/dapp/integration.tsx
create mode 100644 packages/nextjs/pages/dapp/leads.tsx
create mode 100644 packages/nextjs/pages/dapp/settings-billing.tsx
create mode 100644 packages/nextjs/pages/dapp/settings-profile.tsx
create mode 100644 packages/nextjs/pages/dapp/settings-team.tsx
create mode 100644 packages/nextjs/pages/dapp/transactions.tsx
create mode 100644 packages/nextjs/pages/dapp/welcome.tsx
create mode 100644 packages/nextjs/pages/forgot-password.tsx
create mode 100644 packages/nextjs/pages/login.tsx
rename packages/nextjs/pages/{dapp.tsx => orig_dapp.tsx} (97%)
create mode 100644 packages/nextjs/pages/register.tsx
diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx
index 13fa47a..70e94c3 100644
--- a/packages/nextjs/components/Header.tsx
+++ b/packages/nextjs/components/Header.tsx
@@ -1,5 +1,6 @@
+/* eslint-disable @next/next/no-img-element */
import React, { useCallback, useRef, useState } from "react";
-import Image from "next/image";
+// import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import { Bars3Icon, BugAntIcon } from "@heroicons/react/24/outline";
@@ -88,7 +89,7 @@ export const Header = () => {
-
+
Scaffold-ETH
diff --git a/packages/nextjs/components/dash-wind/app/auth.ts b/packages/nextjs/components/dash-wind/app/auth.ts
new file mode 100644
index 0000000..a8e4e33
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/app/auth.ts
@@ -0,0 +1,43 @@
+import axios, { AxiosError, AxiosResponse } from "axios";
+
+const checkAuth = () => {
+ /* Getting token value stored in localstorage, if token is not present we will open login page
+ for all internal dashboard routes */
+ const TOKEN = localStorage.getItem("token");
+ const PUBLIC_ROUTES = ["login", "forgot-password", "register", "documentation"];
+
+ const isPublicPage = PUBLIC_ROUTES.some(r => window.location.href.includes(r));
+
+ if (!TOKEN && !isPublicPage) {
+ window.location.href = "/login";
+ return;
+ } else {
+ axios.defaults.headers.common["Authorization"] = `Bearer ${TOKEN}`;
+
+ axios.interceptors.request.use(
+ function (config) {
+ // UPDATE: Add this code to show global loading indicator
+ document.body.classList.add("loading-indicator");
+ return config;
+ },
+ function (error: AxiosError) {
+ return Promise.reject(error);
+ },
+ );
+
+ axios.interceptors.response.use(
+ function (response: AxiosResponse) {
+ // UPDATE: Add this code to hide global loading indicator
+ document.body.classList.remove("loading-indicator");
+ return response;
+ },
+ function (error: AxiosError) {
+ document.body.classList.remove("loading-indicator");
+ return Promise.reject(error);
+ },
+ );
+ return TOKEN;
+ }
+};
+
+export default checkAuth;
diff --git a/packages/nextjs/components/dash-wind/app/init.ts b/packages/nextjs/components/dash-wind/app/init.ts
new file mode 100644
index 0000000..f713b85
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/app/init.ts
@@ -0,0 +1,20 @@
+import axios from "axios";
+
+const initializeApp = () => {
+ // Setting base URL for all API request via axios
+ axios.defaults.baseURL = process.env.REACT_APP_BASE_URL;
+
+ if (!process.env.NODE_ENV || process.env.NODE_ENV === "development") {
+ // dev code
+ } else {
+ // Prod build code
+
+ // Removing console.log from prod
+ // console.log = () => {};
+ console.log = () => null;
+
+ // init analytics here
+ }
+};
+
+export default initializeApp;
diff --git a/packages/nextjs/components/dash-wind/app/store.ts b/packages/nextjs/components/dash-wind/app/store.ts
new file mode 100644
index 0000000..c5b1657
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/app/store.ts
@@ -0,0 +1,62 @@
+import headerSlice from "../features/common/headerSlice";
+import modalSlice from "../features/common/modalSlice";
+import rightDrawerSlice from "../features/common/rightDrawerSlice";
+import leadsSlice from "../features/leads/leadSlice";
+import { Reducer, ThunkAction, configureStore } from "@reduxjs/toolkit";
+import { createWrapper } from "next-redux-wrapper";
+import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
+import { Action } from "redux";
+
+interface CombinedReducer {
+ header: Reducer<{
+ pageTitle: string;
+ noOfNotifications: number;
+ newNotificationMessage: string;
+ newNotificationStatus: number;
+ }>;
+ rightDrawer: Reducer<{
+ header: string;
+ isOpen: boolean;
+ bodyType: string;
+ extraObject: Record
;
+ }>;
+ modal: Reducer<{
+ title: string;
+ isOpen: boolean;
+ bodyType: string;
+ size: string;
+ extraObject: Record;
+ }>;
+ lead: Reducer<{
+ isLoading: boolean;
+ leads: never[];
+ }>;
+}
+
+const combinedReducer: CombinedReducer = {
+ header: headerSlice,
+ rightDrawer: rightDrawerSlice,
+ modal: modalSlice,
+ lead: leadsSlice,
+};
+
+// export default configureStore({
+// reducer: combinedReducer,
+// });
+const store = configureStore({
+ reducer: combinedReducer,
+});
+
+// const makeStore = context => store;
+const makeStore = () => store;
+
+export type MyStore = ReturnType;
+export type MyState = ReturnType;
+export type MyDispatch = MyStore["dispatch"];
+// export type MyDispatch = typeof store.dispatch;
+export type MyThunk = ThunkAction;
+
+export const useMyDispatch = () => useDispatch();
+export const useMySelector: TypedUseSelectorHook = useSelector;
+
+export const wrapper = createWrapper(makeStore);
diff --git a/packages/nextjs/components/dash-wind/components/CalendarView/index.tsx b/packages/nextjs/components/dash-wind/components/CalendarView/index.tsx
new file mode 100644
index 0000000..e52bef1
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/CalendarView/index.tsx
@@ -0,0 +1,178 @@
+import { useEffect, useState } from "react";
+import { CalendarDetails, CalendarEvents } from "../../types/CalendarTypes";
+import { getTheme } from "./util";
+import moment from "moment";
+import ChevronLeftIcon from "@heroicons/react/24/solid/ChevronLeftIcon";
+import ChevronRightIcon from "@heroicons/react/24/solid/ChevronRightIcon";
+
+interface props {
+ calendarEvents: CalendarEvents;
+ addNewEvent: (date: moment.Moment) => void;
+ openDayDetail: (detail: CalendarDetails) => void;
+}
+
+const CalendarView: React.FC = ({ calendarEvents, addNewEvent, openDayDetail }) => {
+ const today = moment().startOf("day");
+ const weekdays = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
+ const colStartClasses = [
+ "",
+ "col-start-2",
+ "col-start-3",
+ "col-start-4",
+ "col-start-5",
+ "col-start-6",
+ "col-start-7",
+ ];
+
+ const [firstDayOfMonth, setFirstDayOfMonth] = useState(moment().startOf("month"));
+ const [events, setEvents] = useState<[] | CalendarEvents>([]);
+ const [, setCurrMonth] = useState(() => moment(today).format("MMM-yyyy"));
+
+ useEffect(() => {
+ setEvents(calendarEvents);
+ }, [calendarEvents]);
+
+ const allDaysInMonth = () => {
+ const start: moment.Moment = moment(firstDayOfMonth).startOf("week");
+ const end: moment.Moment = moment(moment(firstDayOfMonth).endOf("month")).endOf("week");
+ const days: moment.Moment[] = [];
+ let day: moment.Moment = start;
+ while (day <= end) {
+ days.push(day);
+ day = day.clone().add(1, "d");
+ }
+ return days;
+ };
+
+ const getEventsForCurrentDate = (date: moment.Moment): CalendarEvents => {
+ let filteredEvents = events.filter(e => {
+ if ("startTime" in e) {
+ return moment(date).isSame(moment(e.startTime), "day");
+ }
+ return false;
+ });
+ if (filteredEvents.length > 2) {
+ const originalLength = filteredEvents.length;
+ filteredEvents = filteredEvents.slice(0, 2);
+ filteredEvents.push({ title: `${originalLength - 2} more`, theme: "MORE" });
+ }
+ return filteredEvents;
+ };
+
+ const openAllEventsDetail = (date: moment.Moment, theme: string) => {
+ if (theme != "MORE") return 1;
+ const filteredEvents = events
+ .filter(e => {
+ if ("startTime" in e) {
+ return moment(date).isSame(moment(e.startTime), "day");
+ }
+ return false;
+ })
+ .map(e => {
+ return { title: e.title, theme: e.theme };
+ });
+ openDayDetail({ filteredEvents, title: moment(date).format("D MMM YYYY") });
+ };
+
+ const isToday = (date: moment.Moment) => {
+ return moment(date).isSame(moment(), "day");
+ };
+
+ const isDifferentMonth = (date: moment.Moment) => {
+ return moment(date).month() != moment(firstDayOfMonth).month();
+ };
+
+ // const getPrevMonth = (event) => {
+ const getPrevMonth = () => {
+ const firstDayOfPrevMonth = moment(firstDayOfMonth).add(-1, "M").startOf("month");
+ setFirstDayOfMonth(firstDayOfPrevMonth);
+ setCurrMonth(moment(firstDayOfPrevMonth).format("MMM-yyyy"));
+ };
+
+ // const getCurrentMonth = (event) => {
+ const getCurrentMonth = () => {
+ const firstDayOfCurrMonth = moment().startOf("month");
+ setFirstDayOfMonth(firstDayOfCurrMonth);
+ setCurrMonth(moment(firstDayOfCurrMonth).format("MMM-yyyy"));
+ };
+
+ // const getNextMonth = (event: any) => {
+ const getNextMonth = () => {
+ const firstDayOfNextMonth = moment(firstDayOfMonth).add(1, "M").startOf("month");
+ setFirstDayOfMonth(firstDayOfNextMonth);
+ setCurrMonth(moment(firstDayOfNextMonth).format("MMM-yyyy"));
+ };
+
+ return (
+ <>
+
+
+
+
+ {moment(firstDayOfMonth).format("MMMM yyyy").toString()}
+ Beta
+
+
+
+
+
+
+ Current Month
+
+
+
+
+
+
+ addNewEvent}>
+ Add New Event
+
+
+
+
+
+ {weekdays.map((day, key) => {
+ return (
+
+ {day}
+
+ );
+ })}
+
+
+
+ {allDaysInMonth().map((day, idx) => {
+ return (
+
+
addNewEvent(day)}
+ >
+ {" "}
+ {moment(day).format("D")}
+
+ {getEventsForCurrentDate(day).map((e, k) => {
+ return (
+
openAllEventsDetail(day, e.theme)}
+ className={`text-xs px-2 mt-1 truncate ${getTheme(e.theme) || ""}`}
+ // className={`text-xs px-2 mt-1 truncate ${THEME_BG[e.theme] || ""}`}
+ >
+ {e.title}
+
+ );
+ })}
+
+ );
+ })}
+
+
+ >
+ );
+};
+
+export default CalendarView;
diff --git a/packages/nextjs/components/dash-wind/components/CalendarView/util.ts b/packages/nextjs/components/dash-wind/components/CalendarView/util.ts
new file mode 100644
index 0000000..da9f391
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/CalendarView/util.ts
@@ -0,0 +1,29 @@
+// import moment from "moment";
+// const moment = require("moment");
+
+export function getTheme(theme: string) {
+ const THEME_BG = CALENDAR_EVENT_STYLE;
+ switch (theme) {
+ case "BLUE":
+ return THEME_BG.BLUE;
+ case "GREEN":
+ return THEME_BG.GREEN;
+ case "PURPLE":
+ return THEME_BG.PURPLE;
+ case "ORANGE":
+ return THEME_BG.ORANGE;
+ case "PINK":
+ return THEME_BG.PINK;
+ case "MORE":
+ return THEME_BG.MORE;
+ }
+}
+
+export const CALENDAR_EVENT_STYLE = Object.freeze({
+ BLUE: "bg-blue-200 dark:bg-blue-600 dark:text-blue-100",
+ GREEN: "bg-green-200 dark:bg-green-600 dark:text-green-100",
+ PURPLE: "bg-purple-200 dark:bg-purple-600 dark:text-purple-100",
+ ORANGE: "bg-orange-200 dark:bg-orange-600 dark:text-orange-100",
+ PINK: "bg-pink-200 dark:bg-pink-600 dark:text-pink-100",
+ MORE: "hover:underline cursor-pointer font-medium ",
+});
diff --git a/packages/nextjs/components/dash-wind/components/Cards/TitleCard.tsx b/packages/nextjs/components/dash-wind/components/Cards/TitleCard.tsx
new file mode 100644
index 0000000..58f0e38
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Cards/TitleCard.tsx
@@ -0,0 +1,30 @@
+import { ReactNode } from "react";
+import Subtitle from "../Typography/Subtitle";
+
+interface props {
+ title: string;
+ children: ReactNode;
+ topMargin?: string;
+ TopSideButtons?: JSX.Element;
+}
+
+function TitleCard({ title, children, topMargin, TopSideButtons }: props) {
+ return (
+
+ {/* Title for Card */}
+
+ {title}
+
+ {/* Top side button, show only if present */}
+ {TopSideButtons && {TopSideButtons}
}
+
+
+
+
+ {/** Card Body */}
+
{children}
+
+ );
+}
+
+export default TitleCard;
diff --git a/packages/nextjs/components/dash-wind/components/Input/InputText.tsx b/packages/nextjs/components/dash-wind/components/Input/InputText.tsx
new file mode 100644
index 0000000..b9eb1ba
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Input/InputText.tsx
@@ -0,0 +1,51 @@
+import { useState } from "react";
+
+// import { LEAD_OBJ, LOGIN_OBJ, REGISTER_OBJ, USER_OBJ } from "../../Types/InputTextTypes";
+
+// type InputValues = string | REGISTER_OBJ | LOGIN_OBJ | USER_OBJ | LEAD_OBJ;
+
+interface props {
+ labelTitle?: string;
+ labelStyle?: string;
+ type?: string;
+ containerStyle?: string;
+ defaultValue?: string;
+ placeholder?: string;
+ updateFormValue?: ({ updateType, value }: { updateType: any; value: any }) => void;
+ updateType?: string;
+}
+
+function InputText({
+ labelTitle,
+ labelStyle,
+ type,
+ containerStyle,
+ defaultValue,
+ placeholder,
+ updateFormValue,
+ updateType,
+}: props) {
+ const [value, setValue] = useState(defaultValue);
+
+ function updateInputValue(val: string) {
+ setValue(val);
+ updateFormValue?.({ updateType, value: val });
+ }
+
+ return (
+
+
+ {labelTitle}
+
+ updateInputValue(e.target.value)}
+ className="input input-bordered w-full "
+ />
+
+ );
+}
+
+export default InputText;
diff --git a/packages/nextjs/components/dash-wind/components/Input/SearchBar.tsx b/packages/nextjs/components/dash-wind/components/Input/SearchBar.tsx
new file mode 100644
index 0000000..4b3d463
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Input/SearchBar.tsx
@@ -0,0 +1,30 @@
+import React from "react";
+
+interface props {
+ searchText?: string;
+ styleClass?: string;
+ placeholderText?: string;
+ setSearchText: React.Dispatch>;
+}
+
+function SearchBar({ searchText, styleClass, placeholderText, setSearchText }: props) {
+ function updateSearchInput(value: string) {
+ setSearchText(value);
+ }
+
+ return (
+
+
+ updateSearchInput(e.target.value)}
+ className="input input-sm input-bordered w-full max-w-xs"
+ />
+
+
+ );
+}
+
+export default SearchBar;
diff --git a/packages/nextjs/components/dash-wind/components/Input/SelectBox.tsx b/packages/nextjs/components/dash-wind/components/Input/SelectBox.tsx
new file mode 100644
index 0000000..fb8f64c
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Input/SelectBox.tsx
@@ -0,0 +1,77 @@
+import React, { useState } from "react";
+// import axios from "axios";
+// import capitalize from "capitalize-the-first-letter";
+import InformationCircleIcon from "@heroicons/react/24/outline/InformationCircleIcon";
+
+interface props {
+ labelTitle: string;
+ labelDescription: string;
+ defaultValue: string;
+ containerStyle: string;
+ placeholder: string;
+ labelStyle: string;
+ options: { name: string; value: string }[];
+ updateType: string;
+ updateFormValue: ({ updateType, value }: { updateType: any; value: any }) => void;
+}
+
+function SelectBox({
+ labelTitle,
+ labelDescription,
+ defaultValue,
+ containerStyle,
+ placeholder,
+ labelStyle,
+ options,
+ updateType,
+ updateFormValue,
+}: props) {
+ // const {
+ // labelTitle,
+ // labelDescription,
+ // defaultValue,
+ // containerStyle,
+ // placeholder,
+ // labelStyle,
+ // options,
+ // updateType,
+ // updateFormValue,
+ // } = props;
+
+ const [value, setValue] = useState(defaultValue || "");
+
+ function updateValue(newValue: string) {
+ updateFormValue({ updateType, value: newValue });
+ setValue(newValue);
+ }
+
+ return (
+
+
+
+ {labelTitle}
+ {labelDescription && (
+
+
+
+ )}
+
+
+
+
updateValue(e.target.value)}>
+
+ {placeholder}
+
+ {options.map((o, k) => {
+ return (
+
+ {o.name}
+
+ );
+ })}
+
+
+ );
+}
+
+export default SelectBox;
diff --git a/packages/nextjs/components/dash-wind/components/Input/TextAreaInput.tsx b/packages/nextjs/components/dash-wind/components/Input/TextAreaInput.tsx
new file mode 100644
index 0000000..f517f7f
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Input/TextAreaInput.tsx
@@ -0,0 +1,46 @@
+import { useState } from "react";
+
+interface props {
+ labelTitle?: string;
+ labelStyle?: string;
+ // type: ;
+ containerStyle?: string;
+ defaultValue?: string;
+ placeholder?: string;
+ updateFormValue: ({ updateType, value }: { updateType: any; value: any }) => void;
+ updateType?: string;
+}
+
+function TextAreaInput({
+ labelTitle,
+ labelStyle,
+ // type,
+ containerStyle,
+ defaultValue,
+ placeholder,
+ updateFormValue,
+ updateType,
+}: props) {
+ const [value, setValue] = useState(defaultValue);
+
+ function updateInputValue(val: string) {
+ setValue(val);
+ updateFormValue({ updateType, value: val });
+ }
+
+ return (
+
+
+ {labelTitle}
+
+
+
+ );
+}
+
+export default TextAreaInput;
diff --git a/packages/nextjs/components/dash-wind/components/Input/ToggleInput.tsx b/packages/nextjs/components/dash-wind/components/Input/ToggleInput.tsx
new file mode 100644
index 0000000..c23b0ec
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Input/ToggleInput.tsx
@@ -0,0 +1,44 @@
+// NOTE: Original file was names "ToogleInput"
+import { useState } from "react";
+
+interface props {
+ labelTitle?: string;
+ labelStyle?: string;
+ // type: ;
+ containerStyle?: string;
+ defaultValue?: boolean;
+ // placeholder: ;
+ placeholder?: string;
+ updateFormValue: ({ updateType, value }: { updateType: any; value: any }) => void;
+ updateType?: string;
+}
+
+function ToggleInput({
+ labelTitle,
+ labelStyle,
+ // type,
+ containerStyle,
+ defaultValue,
+ // placeholder,
+ updateFormValue,
+ updateType,
+}: props) {
+ const [value, setValue] = useState(defaultValue);
+
+ const updateToggleValue = () => {
+ setValue(!value);
+ updateFormValue({ updateType, value: !value });
+ };
+
+ return (
+
+
+ {labelTitle}
+ updateToggleValue()} />
+ {/* updateToggleValue()} /> */}
+
+
+ );
+}
+
+export default ToggleInput;
diff --git a/packages/nextjs/components/dash-wind/components/Typography/ErrorText.tsx b/packages/nextjs/components/dash-wind/components/Typography/ErrorText.tsx
new file mode 100644
index 0000000..eb233e9
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Typography/ErrorText.tsx
@@ -0,0 +1,12 @@
+import { ReactNode } from "react";
+
+interface props {
+ styleClass: string;
+ children: ReactNode;
+}
+
+function ErrorText({ styleClass, children }: props) {
+ return {children}
;
+}
+
+export default ErrorText;
diff --git a/packages/nextjs/components/dash-wind/components/Typography/HelperText.tsx b/packages/nextjs/components/dash-wind/components/Typography/HelperText.tsx
new file mode 100644
index 0000000..dd36725
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Typography/HelperText.tsx
@@ -0,0 +1,12 @@
+import { ReactNode } from "react";
+
+interface props {
+ className: string;
+ children: ReactNode;
+}
+
+function HelperText({ className, children }: props) {
+ return {children}
;
+}
+
+export default HelperText;
diff --git a/packages/nextjs/components/dash-wind/components/Typography/Subtitle.tsx b/packages/nextjs/components/dash-wind/components/Typography/Subtitle.tsx
new file mode 100644
index 0000000..251beec
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Typography/Subtitle.tsx
@@ -0,0 +1,11 @@
+import { ReactNode } from "react";
+
+interface props {
+ styleClass: string;
+ children: ReactNode;
+}
+function Subtitle({ styleClass, children }: props) {
+ return {children}
;
+}
+
+export default Subtitle;
diff --git a/packages/nextjs/components/dash-wind/components/Typography/Title.tsx b/packages/nextjs/components/dash-wind/components/Typography/Title.tsx
new file mode 100644
index 0000000..ca691ca
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/components/Typography/Title.tsx
@@ -0,0 +1,13 @@
+import React from "react";
+import { ReactNode } from "react";
+
+interface props {
+ className: string;
+ children: ReactNode;
+}
+
+function Title({ className, children }: props) {
+ return {children}
;
+}
+
+export default Title;
diff --git a/packages/nextjs/components/dash-wind/containers/Header.tsx b/packages/nextjs/components/dash-wind/containers/Header.tsx
new file mode 100644
index 0000000..221d2f3
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/containers/Header.tsx
@@ -0,0 +1,127 @@
+import React, { useEffect, useState } from "react";
+// import Image from "next/image";
+import Link from "next/link";
+import { useRouter } from "next/router";
+import { openRightDrawer } from "../features/common/rightDrawerSlice";
+import { RIGHT_DRAWER_TYPES } from "../utils/globalConstantUtil";
+import { themeChange } from "theme-change";
+import Bars3Icon from "@heroicons/react/24/outline/Bars3Icon";
+import BellIcon from "@heroicons/react/24/outline/BellIcon";
+import MoonIcon from "@heroicons/react/24/outline/MoonIcon";
+import SunIcon from "@heroicons/react/24/outline/SunIcon";
+import UserIcon from "@heroicons/react/24/outline/UserIcon";
+import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store";
+
+function Header() {
+ const dispatch = useMyDispatch();
+ const { noOfNotifications, pageTitle } = useMySelector((state: MyState) => state.header);
+ const [currentTheme, setCurrentTheme] = useState(
+ typeof window !== "undefined" ? localStorage.getItem("theme") : null,
+ );
+ const router = useRouter();
+
+ useEffect(() => {
+ themeChange(false);
+ if (currentTheme === null) {
+ if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
+ setCurrentTheme("dark");
+ } else {
+ setCurrentTheme("light");
+ }
+ }
+ // 👆 false parameter is required for react project
+ }, [currentTheme]);
+
+ // Opening right sidebar for notification
+ const openNotification = () => {
+ dispatch(openRightDrawer({ header: "Notifications", bodyType: RIGHT_DRAWER_TYPES.NOTIFICATION }));
+ };
+
+ function logoutUser() {
+ if (typeof window !== "undefined") {
+ localStorage.clear();
+ }
+ router.push("/");
+ }
+
+ return (
+ <>
+
+ {/* Menu toogle for mobile view or small screen */}
+
+
+
+
+
{pageTitle}
+
+
+
+ {/* Multiple theme selection, uncomment this if you want to enable multiple themes selection,
+ also includes corporate and retro themes in tailwind.config file */}
+
+ {/*
+ Theme
+ Default
+ Dark
+ Corporate
+ Retro
+ */}
+
+ {/* Light and dark theme selection toggle **/}
+
+
+
+
+
+
+ {/* Notification icon */}
+
openNotification()}>
+
+
+ {noOfNotifications > 0 ? (
+ {noOfNotifications}
+ ) : null}
+
+
+
+ {/* Profile icon, opening menu on click */}
+
+
+
+
+
+
+
+
+
+ Profile Settings
+ New
+
+
+
+ Bill History
+
+
+
+ Logout
+
+
+
+
+
+ >
+ );
+}
+
+export default Header;
diff --git a/packages/nextjs/components/dash-wind/containers/Layout.tsx b/packages/nextjs/components/dash-wind/containers/Layout.tsx
new file mode 100644
index 0000000..8aeb745
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/containers/Layout.tsx
@@ -0,0 +1,55 @@
+import { useEffect } from "react";
+import dynamic from "next/dynamic";
+import { removeNotificationMessage } from "../features/common/headerSlice";
+import LeftSidebar from "./LeftSidebar";
+import ModalLayout from "./ModalLayout";
+// import PageContent from "./PageContent";
+import RightSidebar from "./RightSidebar";
+// import { NotificationContainer, NotificationManager } from "react-notifications";
+import "react-notifications/lib/notifications.css";
+import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store";
+
+const NotificationContainer = dynamic(
+ () => import("react-notifications").then(mod => mod.NotificationContainer),
+ { ssr: false }, // This will load the component only on client-side
+);
+
+const NotificationManager = dynamic(
+ () => import("react-notifications").then(mod => mod.NotificationManager),
+ { ssr: false }, // This will load the component only on client-side
+);
+
+function Layout() {
+ const dispatch = useMyDispatch();
+ const { newNotificationMessage, newNotificationStatus } = useMySelector((state: MyState) => state.header);
+
+ useEffect(() => {
+ if (newNotificationMessage !== "") {
+ if (newNotificationStatus === 1) (NotificationManager as any).success(newNotificationMessage, "Success");
+ if (newNotificationStatus === 0) (NotificationManager as any).error(newNotificationMessage, "Error");
+ dispatch(removeNotificationMessage());
+ }
+ }, [dispatch, newNotificationMessage, newNotificationStatus]);
+
+ return (
+ <>
+ {/* Left drawer - containing page content and side bar (always open) */}
+
+
+ {/* Right drawer - containing secondary content like notifications list etc.. */}
+
+
+ {/** Notification layout container */}
+
+
+ {/* Modal layout container */}
+
+ >
+ );
+}
+
+export default Layout;
diff --git a/packages/nextjs/components/dash-wind/containers/LeftSidebar.tsx b/packages/nextjs/components/dash-wind/containers/LeftSidebar.tsx
new file mode 100644
index 0000000..3cd8106
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/containers/LeftSidebar.tsx
@@ -0,0 +1,62 @@
+/* eslint-disable @next/next/no-img-element */
+// import Image from "next/image";
+import Link from "next/link";
+import { useRouter } from "next/router";
+import routes from "../routes/sidebar";
+import SidebarSubmenu from "./SidebarSubmenu";
+
+// import XMarkIcon from "@heroicons/react/24/outline/XMarkIcon";
+
+function LeftSidebar() {
+ const router = useRouter();
+
+ // const close = () => {
+ // document.getElementById("left-sidebar-drawer")?.click();
+ // };
+
+ return (
+ <>
+
+ >
+ );
+}
+
+export default LeftSidebar;
diff --git a/packages/nextjs/components/dash-wind/containers/ModalLayout.tsx b/packages/nextjs/components/dash-wind/containers/ModalLayout.tsx
new file mode 100644
index 0000000..3bd53ac
--- /dev/null
+++ b/packages/nextjs/components/dash-wind/containers/ModalLayout.tsx
@@ -0,0 +1,45 @@
+// import { useEffect } from "react";
+import ConfirmationModalBody from "../features/common/components/ConfirmationModalBody";
+import { ModalRootState, closeModal } from "../features/common/modalSlice";
+import AddLeadModalBody from "../features/leads/components/AddLeadModalBody";
+import { MODAL_BODY_TYPES } from "../utils/globalConstantUtil";
+import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store";
+
+function ModalLayout() {
+ const { isOpen, bodyType, size, extraObject, title }: ModalRootState["modal"] = useMySelector(
+ (state: MyState) => state.modal,
+ );
+ const dispatch = useMyDispatch();
+
+ const close = () => {
+ dispatch(closeModal());
+ };
+
+ return (
+ <>
+ {/* The button to open modal */}
+
+ {/* Put this part before