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 = () => {
- SE2 logo + SE2 logo
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 +

+ + + + +
+
+ +
+
+
+
+ {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 ( +
+ + 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 ( +
+ + + +
+ ); +} + +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 ( +
+ + +
+ ); +} + +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 ( +
+ +
+ ); +} + +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 */} + + {/* */} + + {/* Light and dark theme selection toggle **/} + + + {/* Notification icon */} + + + {/* 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 tag */} +
+
+ +

{title}

+ + {/* Loading modal body according to different modal type */} + { + { + // [MODAL_BODY_TYPES.LEAD_ADD_NEW]: , + [MODAL_BODY_TYPES.LEAD_ADD_NEW]: , + [MODAL_BODY_TYPES.CONFIRMATION]: , + [MODAL_BODY_TYPES.DEFAULT]:
, + }[bodyType] + } +
+
+ + ); +} + +export default ModalLayout; diff --git a/packages/nextjs/components/dash-wind/containers/PageContent.tsx b/packages/nextjs/components/dash-wind/containers/PageContent.tsx new file mode 100644 index 0000000..a379f4d --- /dev/null +++ b/packages/nextjs/components/dash-wind/containers/PageContent.tsx @@ -0,0 +1,36 @@ +import { ReactNode, Suspense } from "react"; +import { useEffect, useRef } from "react"; +import Header from "./Header"; +import SuspenseContent from "./SuspenseContent"; +import { MyState, useMySelector } from "~~/components/dash-wind/app/store"; + +interface props { + children: ReactNode; +} + +function PageContent({ children }: props) { + const mainContentRef = useRef(null); + const { pageTitle } = useMySelector((state: MyState) => state.header); + + // Scroll back to top on new page load + useEffect(() => { + if (mainContentRef.current !== null) { + mainContentRef.current.scroll({ + top: 0, + behavior: "smooth", + }); + } + }, [pageTitle]); + + return ( +
+
+
+ }>{children} +
+
+
+ ); +} + +export default PageContent; diff --git a/packages/nextjs/components/dash-wind/containers/RightSidebar.tsx b/packages/nextjs/components/dash-wind/containers/RightSidebar.tsx new file mode 100644 index 0000000..db4e44b --- /dev/null +++ b/packages/nextjs/components/dash-wind/containers/RightSidebar.tsx @@ -0,0 +1,68 @@ +import CalendarEventsBodyRightDrawer from "../features/calendar/CalendarEventsBodyRightDrawer"; +import NotificationBodyRightDrawer from "../features/common/components/NotificationBodyRightDrawer"; +import { RightDrawerRootState, closeRightDrawer } from "../features/common/rightDrawerSlice"; +import { RIGHT_DRAWER_TYPES } from "../utils/globalConstantUtil"; +import XMarkIcon from "@heroicons/react/24/solid/XMarkIcon"; +import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store"; + +function RightSidebar() { + const { isOpen, bodyType, extraObject, header }: RightDrawerRootState["rightDrawer"] = useMySelector( + (state: MyState) => state.rightDrawer, + ); + const dispatch = useMyDispatch(); + + const close = () => { + dispatch(closeRightDrawer()); + }; + + return ( +
+
+
+ {/* Header */} +
+ + {header} +
+ + {/* ------------------ Content Start ------------------ */} +
+
+ {/* Loading drawer body according to different drawer type */} + { + { + [RIGHT_DRAWER_TYPES.NOTIFICATION]: ( + + ), + [RIGHT_DRAWER_TYPES.CALENDAR_EVENTS]: ( + + ), + [RIGHT_DRAWER_TYPES.DEFAULT]:
, + }[bodyType] + } +
+
+ {/* ------------------ Content End ------------------ */} +
+
+ +
close()}>
+
+ ); +} + +export default RightSidebar; diff --git a/packages/nextjs/components/dash-wind/containers/SidebarSubmenu.tsx b/packages/nextjs/components/dash-wind/containers/SidebarSubmenu.tsx new file mode 100644 index 0000000..ce4a119 --- /dev/null +++ b/packages/nextjs/components/dash-wind/containers/SidebarSubmenu.tsx @@ -0,0 +1,70 @@ +import React, { useEffect, useState } from "react"; +import Link from "next/link"; +import { useRouter } from "next/router"; +import ChevronDownIcon from "@heroicons/react/24/outline/ChevronDownIcon"; + +interface SubmenuItem { + path: string; + icon: React.ComponentType>; + className?: string; + name: string; +} + +interface SidebarSubmenuProps { + submenu: SubmenuItem[]; + name: string; + icon: React.ComponentType>; + className?: string; +} + +function SidebarSubmenu({ submenu, name, icon, className }: SidebarSubmenuProps) { + const router = useRouter(); + const [isExpanded, setIsExpanded] = useState(false); + + /** Open Submenu list if path found in routes, this is for directly loading submenu routes first time */ + useEffect(() => { + if ( + submenu.filter(m => { + return m.path === router.pathname; + })[0] + ) + setIsExpanded(true); + }, [router.pathname, submenu]); + + return ( +
+ {/** Route header */} +
setIsExpanded(!isExpanded)}> + {React.createElement(icon, { className })} {name} + +
+ + {/** Submenu list */} +
+
    + {submenu.map((m, k) => { + return ( +
  • + + {React.createElement(m.icon, { className: m.className })} {m.name} + {router.pathname == m.path ? ( + + ) : null} + +
  • + ); + })} +
+
+
+ ); +} + +export default SidebarSubmenu; diff --git a/packages/nextjs/components/dash-wind/containers/SuspenseContent.tsx b/packages/nextjs/components/dash-wind/containers/SuspenseContent.tsx new file mode 100644 index 0000000..d4499bd --- /dev/null +++ b/packages/nextjs/components/dash-wind/containers/SuspenseContent.tsx @@ -0,0 +1,5 @@ +function SuspenseContent() { + return
Loading...
; +} + +export default SuspenseContent; diff --git a/packages/nextjs/components/dash-wind/features/calendar/CalendarEventsBodyRightDrawer.tsx b/packages/nextjs/components/dash-wind/features/calendar/CalendarEventsBodyRightDrawer.tsx new file mode 100644 index 0000000..ef49d77 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/calendar/CalendarEventsBodyRightDrawer.tsx @@ -0,0 +1,23 @@ +import { getTheme } from "../../components/CalendarView/util"; +import { CalendarMore } from "../../types/CalendarTypes"; + +interface props { + filteredEvents?: CalendarMore[]; + closeRightDrawer?: () => void; +} + +function CalendarEventsBodyRightDrawer({ filteredEvents }: props) { + return ( + <> + {filteredEvents?.map((e, k) => { + return ( +
+ {e.title} +
+ ); + })} + + ); +} + +export default CalendarEventsBodyRightDrawer; diff --git a/packages/nextjs/components/dash-wind/features/calendar/index.tsx b/packages/nextjs/components/dash-wind/features/calendar/index.tsx new file mode 100644 index 0000000..cc3a57e --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/calendar/index.tsx @@ -0,0 +1,46 @@ +import { useState } from "react"; +import CalendarView from "../../components/CalendarView"; +import { CalendarDetails } from "../../types/CalendarTypes"; +import { CALENDAR_INITIAL_EVENTS } from "../../utils/dummyData"; +import { RIGHT_DRAWER_TYPES } from "../../utils/globalConstantUtil"; +import { showNotification } from "../common/headerSlice"; +import { openRightDrawer } from "../common/rightDrawerSlice"; +import moment from "moment"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +const INITIAL_EVENTS = CALENDAR_INITIAL_EVENTS; + +function Calendar() { + const dispatch = useMyDispatch(); + + const [events, setEvents] = useState(INITIAL_EVENTS); + + // Add your own Add Event handler, like opening modal or random event addition + // Format - {title :"", theme: "", startTime : "", endTime : ""}, typescript version comming soon :) + const addNewEvent = (date: moment.Moment) => { + const randomEvent = INITIAL_EVENTS[Math.floor(Math.random() * 10)]; + const newEventObj = { + title: randomEvent.title, + theme: randomEvent.theme, + startTime: moment(date).startOf("day"), + endTime: moment(date).endOf("day"), + }; + setEvents([...events, newEventObj]); + dispatch(showNotification({ message: "New Event Added!", status: 1 })); + }; + + // Open all events of current day in sidebar + const openDayDetail = ({ filteredEvents, title }: CalendarDetails) => { + dispatch( + openRightDrawer({ header: title, bodyType: RIGHT_DRAWER_TYPES.CALENDAR_EVENTS, extraObject: { filteredEvents } }), + ); + }; + + return ( + <> + + + ); +} + +export default Calendar; diff --git a/packages/nextjs/components/dash-wind/features/charts/components/BarChart.tsx b/packages/nextjs/components/dash-wind/features/charts/components/BarChart.tsx new file mode 100644 index 0000000..877de3e --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/charts/components/BarChart.tsx @@ -0,0 +1,46 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +import { BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip } from "chart.js"; +import { Bar } from "react-chartjs-2"; + +ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend); + +function BarChart() { + const options = { + responsive: true, + plugins: { + legend: { + position: "top" as "top" | "bottom" | "left" | "right" | "chartArea", + }, + }, + }; + + const labels = ["January", "February", "March", "April", "May", "June", "July"]; + + const data = { + labels, + datasets: [ + { + label: "Store 1", + data: labels.map(() => { + return Math.random() * 1000 + 500; + }), + backgroundColor: "rgba(255, 99, 132, 1)", + }, + { + label: "Store 2", + data: labels.map(() => { + return Math.random() * 1000 + 500; + }), + backgroundColor: "rgba(53, 162, 235, 1)", + }, + ], + }; + + return ( + + + + ); +} + +export default BarChart; diff --git a/packages/nextjs/components/dash-wind/features/charts/components/DoughnutChart.tsx b/packages/nextjs/components/dash-wind/features/charts/components/DoughnutChart.tsx new file mode 100644 index 0000000..211a40e --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/charts/components/DoughnutChart.tsx @@ -0,0 +1,54 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +// import Subtitle from "../../../components/Typography/Subtitle"; +import { ArcElement, Chart as ChartJS, Filler, Legend, Tooltip } from "chart.js"; +import { Doughnut } from "react-chartjs-2"; + +ChartJS.register(ArcElement, Tooltip, Legend, Tooltip, Filler, Legend); + +function DoughnutChart() { + const options = { + responsive: true, + plugins: { + legend: { + position: "top" as "top" | "bottom" | "left" | "right" | "chartArea", + }, + }, + }; + + const labels = ["Electronics", "Home Applicances", "Beauty", "Furniture", "Watches", "Apparel"]; + + const data = { + labels, + datasets: [ + { + label: "# of Orders", + data: [122, 219, 30, 51, 82, 13], + backgroundColor: [ + "rgba(255, 99, 132, 0.8)", + "rgba(54, 162, 235, 0.8)", + "rgba(255, 206, 86, 0.8)", + "rgba(75, 192, 192, 0.8)", + "rgba(153, 102, 255, 0.8)", + "rgba(255, 159, 64, 0.8)", + ], + borderColor: [ + "rgba(255, 99, 132, 1)", + "rgba(54, 162, 235, 1)", + "rgba(255, 206, 86, 1)", + "rgba(75, 192, 192, 1)", + "rgba(153, 102, 255, 1)", + "rgba(255, 159, 64, 1)", + ], + borderWidth: 1, + }, + ], + }; + + return ( + + + + ); +} + +export default DoughnutChart; diff --git a/packages/nextjs/components/dash-wind/features/charts/components/LineChart.tsx b/packages/nextjs/components/dash-wind/features/charts/components/LineChart.tsx new file mode 100644 index 0000000..7ec82a6 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/charts/components/LineChart.tsx @@ -0,0 +1,51 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +import { + CategoryScale, + Chart as ChartJS, + Filler, + Legend, + LineElement, + LinearScale, + PointElement, + Title, + Tooltip, +} from "chart.js"; +import { Line } from "react-chartjs-2"; + +ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Filler, Legend); + +function LineChart() { + const options = { + responsive: true, + plugins: { + legend: { + position: "top" as "top" | "bottom" | "left" | "right" | "chartArea", + }, + }, + }; + + const labels = ["January", "February", "March", "April", "May", "June", "July"]; + + const data = { + labels, + datasets: [ + { + fill: true, + label: "MAU", + data: labels.map(() => { + return Math.random() * 100 + 500; + }), + borderColor: "rgb(53, 162, 235)", + backgroundColor: "rgba(53, 162, 235, 0.5)", + }, + ], + }; + + return ( + + + + ); +} + +export default LineChart; diff --git a/packages/nextjs/components/dash-wind/features/charts/components/PieChart.tsx b/packages/nextjs/components/dash-wind/features/charts/components/PieChart.tsx new file mode 100644 index 0000000..822b9ef --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/charts/components/PieChart.tsx @@ -0,0 +1,54 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +// import Subtitle from "../../../components/Typography/Subtitle"; +import { ArcElement, Chart as ChartJS, Filler, Legend, Tooltip } from "chart.js"; +import { Pie } from "react-chartjs-2"; + +ChartJS.register(ArcElement, Tooltip, Legend, Tooltip, Filler, Legend); + +function PieChart() { + const options = { + responsive: true, + plugins: { + legend: { + position: "top" as "top" | "bottom" | "left" | "right" | "chartArea", + }, + }, + }; + + const labels = ["India", "Middle East", "Europe", "US", "Latin America", "Asia(non-india)"]; + + const data = { + labels, + datasets: [ + { + label: "# of Orders", + data: [122, 219, 30, 51, 82, 13], + backgroundColor: [ + "rgba(255, 99, 255, 0.8)", + "rgba(54, 162, 235, 0.8)", + "rgba(255, 206, 255, 0.8)", + "rgba(75, 192, 255, 0.8)", + "rgba(153, 102, 255, 0.8)", + "rgba(255, 159, 255, 0.8)", + ], + borderColor: [ + "rgba(255, 99, 255, 1)", + "rgba(54, 162, 235, 1)", + "rgba(255, 206, 255, 1)", + "rgba(75, 192, 255, 1)", + "rgba(153, 102, 255, 1)", + "rgba(255, 159, 255, 1)", + ], + borderWidth: 1, + }, + ], + }; + + return ( + + + + ); +} + +export default PieChart; diff --git a/packages/nextjs/components/dash-wind/features/charts/components/ScatterChart.tsx b/packages/nextjs/components/dash-wind/features/charts/components/ScatterChart.tsx new file mode 100644 index 0000000..91ea035 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/charts/components/ScatterChart.tsx @@ -0,0 +1,44 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +import { ArcElement, Chart as ChartJS, Filler, Legend, Tooltip } from "chart.js"; +import { Scatter } from "react-chartjs-2"; + +ChartJS.register(ArcElement, Tooltip, Legend, Tooltip, Filler, Legend); + +function ScatterChart() { + const options = { + scales: { + y: { + beginAtZero: true, + }, + }, + }; + + const data = { + datasets: [ + { + label: "Orders > 1k", + data: Array.from({ length: 100 }, () => ({ + x: Math.random() * 11, + y: Math.random() * 31, + })), + backgroundColor: "rgba(255, 99, 132, 1)", + }, + { + label: "Orders > 2K", + data: Array.from({ length: 100 }, () => ({ + x: Math.random() * 12, + y: Math.random() * 12, + })), + backgroundColor: "rgba(0, 0, 255, 1)", + }, + ], + }; + + return ( + + + + ); +} + +export default ScatterChart; diff --git a/packages/nextjs/components/dash-wind/features/charts/components/StackBarChart.tsx b/packages/nextjs/components/dash-wind/features/charts/components/StackBarChart.tsx new file mode 100644 index 0000000..e8f08e4 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/charts/components/StackBarChart.tsx @@ -0,0 +1,56 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +import { BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip } from "chart.js"; +import { Bar } from "react-chartjs-2"; + +ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend); + +function StackBarChart() { + const options = { + responsive: true, + scales: { + x: { + stacked: true, + }, + y: { + stacked: true, + }, + }, + }; + + const labels = ["January", "February", "March", "April", "May", "June", "July"]; + + const data = { + labels, + datasets: [ + { + label: "Store 1", + data: labels.map(() => { + return Math.random() * 1000 + 500; + }), + backgroundColor: "rgba(255, 99, 132, 1)", + }, + { + label: "Store 2", + data: labels.map(() => { + return Math.random() * 1000 + 500; + }), + backgroundColor: "rgba(53, 162, 235, 1)", + }, + { + label: "Store 3", + data: labels.map(() => { + return Math.random() * 1000 + 500; + }), + backgroundColor: "rgba(235, 162, 235, 1)", + }, + ], + }; + + return ( + + + + ); +} + +export default StackBarChart; diff --git a/packages/nextjs/components/dash-wind/features/charts/index.tsx b/packages/nextjs/components/dash-wind/features/charts/index.tsx new file mode 100644 index 0000000..2a1ce5b --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/charts/index.tsx @@ -0,0 +1,57 @@ +import { useState } from "react"; +import { DateValue } from "../../types/DateTypes"; +import BarChart from "./components/BarChart"; +import DoughnutChart from "./components/DoughnutChart"; +import LineChart from "./components/LineChart"; +import PieChart from "./components/PieChart"; +import ScatterChart from "./components/ScatterChart"; +import StackBarChart from "./components/StackBarChart"; +import Datepicker, { DateValueType } from "react-tailwindcss-datepicker"; + +function Charts() { + const [dateValue, setDateValue] = useState({ + startDate: new Date(), + endDate: new Date(), + }); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const handleDatePickerValueChange = (newValue: DateValueType, e?: HTMLInputElement | null | undefined) => { + if (newValue !== null) { + console.log("newValue:", newValue); + setDateValue(newValue); + } + }; + + return ( + <> + + {/** ---------------------- Different charts ------------------------- */} +
+ + +
+ +
+ + +
+ +
+ + +
+ + ); +} + +export default Charts; diff --git a/packages/nextjs/components/dash-wind/features/common/components/ConfirmationModalBody.tsx b/packages/nextjs/components/dash-wind/features/common/components/ConfirmationModalBody.tsx new file mode 100644 index 0000000..7f169bf --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/common/components/ConfirmationModalBody.tsx @@ -0,0 +1,44 @@ +import { CONFIRMATION_MODAL_CLOSE_TYPES } from "../../../utils/globalConstantUtil"; +import { deleteLead } from "../../leads/leadSlice"; +import { showNotification } from "../headerSlice"; +// import axios from "axios"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +interface props { + extraObject: Record; + closeModal: () => void; +} + +function ConfirmationModalBody({ extraObject, closeModal }: props) { + const dispatch = useMyDispatch(); + + // const { message, type, _id, index } = extraObject; + const { message, type, index } = extraObject; + + const proceedWithYes = async () => { + if (type === CONFIRMATION_MODAL_CLOSE_TYPES.LEAD_DELETE) { + // positive response, call api or dispatch redux function + dispatch(deleteLead({ index })); + dispatch(showNotification({ message: "Lead Deleted!", status: 1 })); + } + closeModal(); + }; + + return ( + <> +

{message}

+ +
+ + + +
+ + ); +} + +export default ConfirmationModalBody; diff --git a/packages/nextjs/components/dash-wind/features/common/components/NotificationBodyRightDrawer.tsx b/packages/nextjs/components/dash-wind/features/common/components/NotificationBodyRightDrawer.tsx new file mode 100644 index 0000000..319a50d --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/common/components/NotificationBodyRightDrawer.tsx @@ -0,0 +1,20 @@ +interface props { + closeRightDrawer?: () => void; +} +function NotificationBodyRightDrawer({}: props) { + return ( + <> + {[...Array(15)].map((_, i) => { + return ( +
+ {i % 2 === 0 + ? `Your sales has increased by 30% yesterday` + : `Total likes for instagram post - New launch this week, has crossed 100k `} +
+ ); + })} + + ); +} + +export default NotificationBodyRightDrawer; diff --git a/packages/nextjs/components/dash-wind/features/common/headerSlice.ts b/packages/nextjs/components/dash-wind/features/common/headerSlice.ts new file mode 100644 index 0000000..fb9b25a --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/common/headerSlice.ts @@ -0,0 +1,45 @@ +import { PayloadAction, createSlice } from "@reduxjs/toolkit"; + +export interface HeaderRootState { + header: { + pageTitle: string; + noOfNotifications: number; + newNotificationMessage: string; + newNotificationStatus: number; + }; +} + +export interface HeaderState { + pageTitle: string; + noOfNotifications: number; + newNotificationMessage: string; + newNotificationStatus: number; +} + +export const headerSlice = createSlice({ + name: "header", + initialState: { + pageTitle: "Home", // current page title state management + noOfNotifications: 15, // no of unread notifications + newNotificationMessage: "", // message of notification to be shown + newNotificationStatus: 1, // to check the notification type - success/ error/ info + }, + reducers: { + setPageTitle: (state: HeaderState, action: PayloadAction<{ title: string }>) => { + state.pageTitle = action.payload.title; + }, + + removeNotificationMessage: (state: HeaderState) => { + state.newNotificationMessage = ""; + }, + + showNotification: (state: HeaderState, action: PayloadAction<{ message: string; status: number }>) => { + state.newNotificationMessage = action.payload.message; + state.newNotificationStatus = action.payload.status; + }, + }, +}); + +export const { setPageTitle, removeNotificationMessage, showNotification } = headerSlice.actions; + +export default headerSlice.reducer; diff --git a/packages/nextjs/components/dash-wind/features/common/modalSlice.ts b/packages/nextjs/components/dash-wind/features/common/modalSlice.ts new file mode 100644 index 0000000..b433512 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/common/modalSlice.ts @@ -0,0 +1,51 @@ +import { PayloadAction, createSlice } from "@reduxjs/toolkit"; + +export interface ModalRootState { + modal: { + title: string; + isOpen: boolean; + bodyType: string; + size: string; + extraObject: Record; + }; +} + +interface ModalState { + title?: string; + isOpen?: boolean; + bodyType?: string; + size?: string; + extraObject?: Record; +} + +export const modalSlice = createSlice({ + name: "modal", + initialState: { + title: "", // current title state management + isOpen: false, // modal state management for opening closing + bodyType: "", // modal content management + size: "", // modal content management + extraObject: {}, + }, + reducers: { + openModal: (state: ModalState, action: PayloadAction) => { + const { title, bodyType, extraObject, size } = action.payload; + state.isOpen = true; + state.bodyType = bodyType; + state.title = title; + state.size = size || "md"; + state.extraObject = extraObject; + }, + + closeModal: (state: ModalState) => { + state.isOpen = false; + state.bodyType = ""; + state.title = ""; + state.extraObject = {}; + }, + }, +}); + +export const { openModal, closeModal } = modalSlice.actions; + +export default modalSlice.reducer; diff --git a/packages/nextjs/components/dash-wind/features/common/rightDrawerSlice.ts b/packages/nextjs/components/dash-wind/features/common/rightDrawerSlice.ts new file mode 100644 index 0000000..f2c7c01 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/common/rightDrawerSlice.ts @@ -0,0 +1,47 @@ +import { PayloadAction, createSlice } from "@reduxjs/toolkit"; + +export interface RightDrawerRootState { + rightDrawer: { + header: string; + isOpen: boolean; + bodyType: string; + extraObject: Record; + }; +} + +interface RightDrawerState { + header?: string; + isOpen?: boolean; + bodyType: string; + extraObject?: Record; +} + +export const rightDrawerSlice = createSlice({ + name: "rightDrawer", + initialState: { + header: "", // current title state management + isOpen: false, // right drawer state management for opening closing + bodyType: "", // right drawer content management + extraObject: {}, + }, + reducers: { + openRightDrawer: (state: RightDrawerState, action: PayloadAction) => { + const { header, bodyType, extraObject } = action.payload; + state.isOpen = true; + state.bodyType = bodyType; + state.header = header; + state.extraObject = extraObject; + }, + + closeRightDrawer: (state: RightDrawerState) => { + state.isOpen = false; + state.bodyType = ""; + state.header = ""; + state.extraObject = {}; + }, + }, +}); + +export const { openRightDrawer, closeRightDrawer } = rightDrawerSlice.actions; + +export default rightDrawerSlice.reducer; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/AmountStats.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/AmountStats.tsx new file mode 100644 index 0000000..37d72d9 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/AmountStats.tsx @@ -0,0 +1,23 @@ +function AmountStats({}) { + return ( +
+
+
Amount to be Collected
+
$25,600
+
+ +
+
+ +
+
Cash in hand
+
$5,600
+
+ +
+
+
+ ); +} + +export default AmountStats; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/BarChart.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/BarChart.tsx new file mode 100644 index 0000000..b06470f --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/BarChart.tsx @@ -0,0 +1,46 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +import { BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip } from "chart.js"; +import { Bar } from "react-chartjs-2"; + +ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend); + +function BarChart() { + const options = { + responsive: true, + plugins: { + legend: { + position: "top" as "top" | "bottom" | "left" | "right" | "chartArea", + }, + }, + }; + + const labels = ["January", "February", "March", "April", "May", "June", "July"]; + + const data = { + labels, + datasets: [ + { + label: "Store 1", + data: labels.map(() => { + return Math.random() * 1000 + 500; + }), + backgroundColor: "rgba(255, 99, 132, 1)", + }, + { + label: "Store 2", + data: labels.map(() => { + return Math.random() * 1000 + 500; + }), + backgroundColor: "rgba(53, 162, 235, 1)", + }, + ], + }; + + return ( + + + + ); +} + +export default BarChart; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/DashboardStats.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/DashboardStats.tsx new file mode 100644 index 0000000..6da47e8 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/DashboardStats.tsx @@ -0,0 +1,29 @@ +interface props { + title: string; + icon: JSX.Element; + value: string; + description: string; + colorIndex: number; +} +function DashboardStats({ title, icon, value, description, colorIndex }: props) { + const COLORS = ["primary", "primary"]; + + const getDescStyle = () => { + if (description.includes("↗︎")) return "font-bold text-green-700 dark:text-green-300"; + else if (description.includes("↙")) return "font-bold text-rose-500 dark:text-red-400"; + else return ""; + }; + + return ( +
+
+
{icon}
+
{title}
+
{value}
+
{description}
+
+
+ ); +} + +export default DashboardStats; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/DashboardTopBar.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/DashboardTopBar.tsx new file mode 100644 index 0000000..62e86de --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/DashboardTopBar.tsx @@ -0,0 +1,97 @@ +import { useState } from "react"; +// import SelectBox from "../../../components/Input/SelectBox"; +import Datepicker, { DateValueType } from "react-tailwindcss-datepicker"; +import ArrowDownTrayIcon from "@heroicons/react/24/outline/ArrowDownTrayIcon"; +import ArrowPathIcon from "@heroicons/react/24/outline/ArrowPathIcon"; +import EllipsisVerticalIcon from "@heroicons/react/24/outline/EllipsisVerticalIcon"; +import EnvelopeIcon from "@heroicons/react/24/outline/EnvelopeIcon"; +import ShareIcon from "@heroicons/react/24/outline/ShareIcon"; +import { DateValue } from "~~/components/dash-wind/types/DateTypes"; + +interface props { + updateDashboardPeriod: (newRange: DateValue) => void; +} + +// const periodOptions = [ +// { name: "Today", value: "TODAY" }, +// { name: "Yesterday", value: "YESTERDAY" }, +// { name: "This Week", value: "THIS_WEEK" }, +// { name: "Last Week", value: "LAST_WEEK" }, +// { name: "This Month", value: "THIS_MONTH" }, +// { name: "Last Month", value: "LAST_MONTH" }, +// ]; + +function DashboardTopBar({ updateDashboardPeriod }: props) { + const [dateValue, setDateValue] = useState({ + startDate: new Date(), + endDate: new Date(), + }); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const handleDatePickerValueChange = (newValue: DateValueType, e?: HTMLInputElement | null | undefined) => { + if (newValue !== null) { + console.log("newValue:", newValue); + setDateValue(newValue); + updateDashboardPeriod(newValue); + } + }; + + return ( +
+
+ + {/* */} +
+
+ + + + +
+
+ ); +} + +export default DashboardTopBar; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/DoughnutChart.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/DoughnutChart.tsx new file mode 100644 index 0000000..211a40e --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/DoughnutChart.tsx @@ -0,0 +1,54 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +// import Subtitle from "../../../components/Typography/Subtitle"; +import { ArcElement, Chart as ChartJS, Filler, Legend, Tooltip } from "chart.js"; +import { Doughnut } from "react-chartjs-2"; + +ChartJS.register(ArcElement, Tooltip, Legend, Tooltip, Filler, Legend); + +function DoughnutChart() { + const options = { + responsive: true, + plugins: { + legend: { + position: "top" as "top" | "bottom" | "left" | "right" | "chartArea", + }, + }, + }; + + const labels = ["Electronics", "Home Applicances", "Beauty", "Furniture", "Watches", "Apparel"]; + + const data = { + labels, + datasets: [ + { + label: "# of Orders", + data: [122, 219, 30, 51, 82, 13], + backgroundColor: [ + "rgba(255, 99, 132, 0.8)", + "rgba(54, 162, 235, 0.8)", + "rgba(255, 206, 86, 0.8)", + "rgba(75, 192, 192, 0.8)", + "rgba(153, 102, 255, 0.8)", + "rgba(255, 159, 64, 0.8)", + ], + borderColor: [ + "rgba(255, 99, 132, 1)", + "rgba(54, 162, 235, 1)", + "rgba(255, 206, 86, 1)", + "rgba(75, 192, 192, 1)", + "rgba(153, 102, 255, 1)", + "rgba(255, 159, 64, 1)", + ], + borderWidth: 1, + }, + ], + }; + + return ( + + + + ); +} + +export default DoughnutChart; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/LineChart.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/LineChart.tsx new file mode 100644 index 0000000..53fa9d7 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/LineChart.tsx @@ -0,0 +1,51 @@ +import TitleCard from "../../../components/Cards/TitleCard"; +import { + CategoryScale, + Chart as ChartJS, + Filler, + Legend, + LineElement, + LinearScale, + PointElement, + Title, + Tooltip, +} from "chart.js"; +import { Line } from "react-chartjs-2"; + +ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Filler, Legend); + +function LineChart() { + const options = { + responsive: true, + plugins: { + legend: { + position: "top" as "top" | "bottom" | "left" | "right" | "chartArea", + }, + }, + }; + + const labels = ["January", "February", "March", "April", "May", "June", "July"]; + + const data = { + labels, + datasets: [ + { + fill: true, + label: "MAU", + data: labels.map(() => { + return Math.random() * 100 + 500; + }), + borderColor: "rgb(53, 162, 235)", + backgroundColor: "rgba(53, 162, 235, 0.5)", + }, + ], + }; + + return ( + + + + ); +} + +export default LineChart; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/PageStats.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/PageStats.tsx new file mode 100644 index 0000000..f2e3970 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/PageStats.tsx @@ -0,0 +1,28 @@ +import BoltIcon from "@heroicons/react/24/outline/BoltIcon"; +import HeartIcon from "@heroicons/react/24/outline/HeartIcon"; + +function PageStats({}) { + return ( +
+
+
+ +
+
Total Likes
+
25.6K
+
21% more than last month
+
+ +
+
+ +
+
Page Views
+
2.6M
+
14% more than last month
+
+
+ ); +} + +export default PageStats; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/components/UserChannels.tsx b/packages/nextjs/components/dash-wind/features/dashboard/components/UserChannels.tsx new file mode 100644 index 0000000..93734fd --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/components/UserChannels.tsx @@ -0,0 +1,43 @@ +import TitleCard from "../../../components/Cards/TitleCard"; + +const userSourceData = [ + { source: "Facebook Ads", count: "26,345", conversionPercent: 10.2 }, + { source: "Google Ads", count: "21,341", conversionPercent: 11.7 }, + { source: "Instagram Ads", count: "34,379", conversionPercent: 12.4 }, + { source: "Affiliates", count: "12,359", conversionPercent: 20.9 }, + { source: "Organic", count: "10,345", conversionPercent: 10.3 }, +]; + +function UserChannels() { + return ( + + {/** Table Data */} +
+ + + + + + + + + + + {userSourceData.map((u, k) => { + return ( + + + + + + + ); + })} + +
SourceNo of UsersConversion
{k + 1}{u.source}{u.count}{`${u.conversionPercent}%`}
+
+
+ ); +} + +export default UserChannels; diff --git a/packages/nextjs/components/dash-wind/features/dashboard/index.tsx b/packages/nextjs/components/dash-wind/features/dashboard/index.tsx new file mode 100644 index 0000000..45f9e2a --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/dashboard/index.tsx @@ -0,0 +1,80 @@ +// import { useState } from "react"; +import { DateValue } from "../../types/DateTypes"; +import { showNotification } from "../common/headerSlice"; +import AmountStats from "./components/AmountStats"; +import BarChart from "./components/BarChart"; +import DashboardStats from "./components/DashboardStats"; +import DashboardTopBar from "./components/DashboardTopBar"; +import DoughnutChart from "./components/DoughnutChart"; +import LineChart from "./components/LineChart"; +import PageStats from "./components/PageStats"; +import UserChannels from "./components/UserChannels"; +import CircleStackIcon from "@heroicons/react/24/outline/CircleStackIcon"; +import CreditCardIcon from "@heroicons/react/24/outline/CreditCardIcon"; +import UserGroupIcon from "@heroicons/react/24/outline/UserGroupIcon"; +import UsersIcon from "@heroicons/react/24/outline/UsersIcon"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +const statsData = [ + { title: "New Users", value: "34.7k", icon: , description: "↗︎ 2300 (22%)" }, + { + title: "Total Sales", + value: "$34,545", + icon: , + description: "Current month", + }, + { + title: "Pending Leads", + value: "450", + icon: , + description: "50 in hot leads", + }, + { title: "Active Users", value: "5.6k", icon: , description: "↙ 300 (18%)" }, +]; + +function Dashboard() { + const dispatch = useMyDispatch(); + + const updateDashboardPeriod = (newRange: DateValue) => { + // Dashboard range changed, write code to refresh your values + dispatch( + showNotification({ message: `Period updated to ${newRange.startDate} to ${newRange.endDate}`, status: 1 }), + ); + }; + + return ( + <> + {/** ---------------------- Select Period Content ------------------------- */} + + + {/** ---------------------- Different stats content 1 ------------------------- */} +
+ {statsData.map((d, k) => { + return ; + })} +
+ + {/** ---------------------- Different charts ------------------------- */} +
+ + +
+ + {/** ---------------------- Different stats content 2 ------------------------- */} + +
+ + +
+ + {/** ---------------------- User source channels table ------------------------- */} + +
+ + +
+ + ); +} + +export default Dashboard; diff --git a/packages/nextjs/components/dash-wind/features/integration/index.tsx b/packages/nextjs/components/dash-wind/features/integration/index.tsx new file mode 100644 index 0000000..fc522dd --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/integration/index.tsx @@ -0,0 +1,102 @@ +/* eslint-disable @next/next/no-img-element */ +import { useState } from "react"; +// import Image from "next/image"; +import TitleCard from "../../components/Cards/TitleCard"; +import { showNotification } from "../common/headerSlice"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +const INITIAL_INTEGRATION_LIST = [ + { + name: "Slack", + icon: "https://cdn-icons-png.flaticon.com/512/2111/2111615.png", + isActive: true, + description: "Slack is an instant messaging program designed by Slack Technologies and owned by Salesforce.", + }, + { + name: "Facebook", + icon: "https://cdn-icons-png.flaticon.com/512/124/124010.png", + isActive: false, + description: "Meta Platforms, Inc., doing business as Meta and formerly named Facebook, Inc., and TheFacebook.", + }, + { + name: "Linkedin", + icon: "https://cdn-icons-png.flaticon.com/512/174/174857.png", + isActive: true, + description: + "LinkedIn is a business and employment-focused social media platform that works through websites and mobile apps.", + }, + { + name: "Google Ads", + icon: "https://cdn-icons-png.flaticon.com/512/2301/2301145.png", + isActive: false, + description: + "Google Ads is an online advertising platform developed by Google, where advertisers bid to display brief advertisements, service offerings", + }, + { + name: "Gmail", + icon: "https://cdn-icons-png.flaticon.com/512/5968/5968534.png", + isActive: false, + description: + "Gmail is a free email service provided by Google. As of 2019, it had 1.5 billion active users worldwide.", + }, + { + name: "Salesforce", + icon: "https://cdn-icons-png.flaticon.com/512/5968/5968880.png", + isActive: false, + description: + "It provides customer relationship management software and applications focused on sales, customer service, marketing automation.", + }, + { + name: "Hubspot", + icon: "https://cdn-icons-png.flaticon.com/512/5968/5968872.png", + isActive: false, + description: + "American developer and marketer of software products for inbound marketing, sales, and customer service.", + }, +]; + +function Integration() { + const dispatch = useMyDispatch(); + + const [integrationList, setIntegrationList] = useState(INITIAL_INTEGRATION_LIST); + + const updateIntegrationStatus = (index: number) => { + const integration = integrationList[index]; + setIntegrationList( + integrationList.map((i, k) => { + if (k === index) return { ...i, isActive: !i.isActive }; + return i; + }), + ); + dispatch( + showNotification({ message: `${integration.name} ${integration.isActive ? "disabled" : "enabled"}`, status: 1 }), + ); + }; + + return ( + <> +
+ {integrationList.map((i, k) => { + return ( + +

+ icon + {i.description} +

+
+ updateIntegrationStatus(k)} + /> +
+
+ ); + })} +
+ + ); +} + +export default Integration; diff --git a/packages/nextjs/components/dash-wind/features/leads/components/AddLeadModalBody.tsx b/packages/nextjs/components/dash-wind/features/leads/components/AddLeadModalBody.tsx new file mode 100644 index 0000000..746303c --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/leads/components/AddLeadModalBody.tsx @@ -0,0 +1,90 @@ +import { useState } from "react"; +import InputText from "../../../components/Input/InputText"; +import ErrorText from "../../../components/Typography/ErrorText"; +import { showNotification } from "../../common/headerSlice"; +import { addNewLead } from "../leadSlice"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; +import { UpdateFormValues } from "~~/components/dash-wind/types/FormTypes"; + +interface props { + closeModal: () => void; +} + +const INITIAL_LEAD_OBJ = { + first_name: "", + last_name: "", + email: "", +}; + +// function AddLeadModalBody({ closeModal, extraObject }) { +function AddLeadModalBody({ closeModal }: props) { + const dispatch = useMyDispatch(); + // const [loading, setLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState(""); + const [leadObj, setLeadObj] = useState(INITIAL_LEAD_OBJ); + + const saveNewLead = () => { + if (leadObj.first_name.trim() === "") return setErrorMessage("First Name is required!"); + else if (leadObj.email.trim() === "") return setErrorMessage("Email id is required!"); + else { + const newLeadObj = { + id: 7, + email: leadObj.email, + first_name: leadObj.first_name, + last_name: leadObj.last_name, + avatar: "https://reqres.in/img/faces/1-image.jpg", + }; + dispatch(addNewLead({ newLeadObj })); + dispatch(showNotification({ message: "New Lead Added!", status: 1 })); + closeModal(); + } + }; + + const updateFormValue = ({ updateType, value }: UpdateFormValues) => { + setErrorMessage(""); + setLeadObj({ ...leadObj, [updateType]: value }); + }; + + return ( + <> + + + + + + + {errorMessage} +
+ + +
+ + ); +} + +export default AddLeadModalBody; diff --git a/packages/nextjs/components/dash-wind/features/leads/index.tsx b/packages/nextjs/components/dash-wind/features/leads/index.tsx new file mode 100644 index 0000000..18d15f1 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/leads/index.tsx @@ -0,0 +1,116 @@ +/* eslint-disable @next/next/no-img-element */ +import { useEffect } from "react"; +// import Image from "next/image"; +import TitleCard from "../../components/Cards/TitleCard"; +import { CONFIRMATION_MODAL_CLOSE_TYPES, MODAL_BODY_TYPES } from "../../utils/globalConstantUtil"; +// import { showNotification } from "../common/headerSlice"; +import { openModal } from "../common/modalSlice"; +import { Lead, getLeadsContent } from "./leadSlice"; +import moment from "moment"; +import TrashIcon from "@heroicons/react/24/outline/TrashIcon"; +import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store"; + +const TopSideButtons = () => { + const dispatch = useMyDispatch(); + + const openAddNewLeadModal = () => { + dispatch(openModal({ title: "Add New Lead", bodyType: MODAL_BODY_TYPES.LEAD_ADD_NEW })); + }; + + return ( +
+ +
+ ); +}; + +function Leads() { + const { leads } = useMySelector((state: MyState) => state.lead); + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(getLeadsContent()); + }, [dispatch]); + + const getDummyStatus = (index: number) => { + if (index % 5 === 0) return
Not Interested
; + else if (index % 5 === 1) return
In Progress
; + else if (index % 5 === 2) return
Sold
; + else if (index % 5 === 3) return
Need Followup
; + else return
Open
; + }; + + const deleteCurrentLead = (index: number) => { + dispatch( + openModal({ + title: "Confirmation", + bodyType: MODAL_BODY_TYPES.CONFIRMATION, + extraObject: { + message: `Are you sure you want to delete this lead?`, + type: CONFIRMATION_MODAL_CLOSE_TYPES.LEAD_DELETE, + index, + }, + }), + ); + }; + + return ( + <> + }> + {/* Leads List in table format loaded from slice after api call */} +
+ + + + + + + + + + + + + {leads.map((l: Lead, k: number) => { + return ( + + + + + + + + + ); + })} + +
NameEmail IdCreated AtStatusAssigned To
+
+
+
+ Avatar +
+
+
+
{l.first_name}
+
{l.last_name}
+
+
+
{l.email} + {moment(new Date()) + .add(-5 * (k + 2), "days") + .format("DD MMM YY")} + {getDummyStatus(k)}{l.last_name} + +
+
+
+ + ); +} + +export default Leads; diff --git a/packages/nextjs/components/dash-wind/features/leads/leadSlice.ts b/packages/nextjs/components/dash-wind/features/leads/leadSlice.ts new file mode 100644 index 0000000..155bc8d --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/leads/leadSlice.ts @@ -0,0 +1,74 @@ +import { ActionReducerMapBuilder, PayloadAction, createAsyncThunk, createSlice } from "@reduxjs/toolkit"; +import axios from "axios"; + +export type Lead = { + id: number; + email: string; + first_name: string; + last_name: string; + avatar: string; +}; + +export interface LeadRootState { + leads: { + isLoading: boolean; + leads: Lead[]; + }; +} + +interface LeadState { + isLoading: boolean; + leads: Lead[]; +} + +export const getLeadsContent = createAsyncThunk("/leads/content", async () => { + const response = await axios.get("/api/users?page=2", {}); + return response.data; +}); + +export const leadsSlice = createSlice({ + name: "leads", + initialState: { + isLoading: false, + leads: [], + }, + reducers: { + addNewLead: ( + state: LeadState, + action: PayloadAction<{ + newLeadObj: { + id: number; + email: string; + first_name: string; + last_name: string; + avatar: string; + }; + }>, + ) => { + const { newLeadObj } = action.payload; + state.leads = [...state.leads, newLeadObj]; + }, + + deleteLead: (state: LeadState, action: PayloadAction<{ index: number }>) => { + const { index } = action.payload; + state.leads.splice(index, 1); + }, + }, + + extraReducers: (builder: ActionReducerMapBuilder) => { + builder.addCase(getLeadsContent.pending, (state: LeadState) => { + state.isLoading = true; + }); + builder.addCase(getLeadsContent.fulfilled, (state: LeadState, action: PayloadAction) => { + state.leads = action.payload; + state.isLoading = false; + }); + builder.addCase(getLeadsContent.rejected, (state: LeadState) => { + state.isLoading = false; + }); + }, +}); + +export const { addNewLead, deleteLead } = leadsSlice.actions; + +export default leadsSlice.reducer; diff --git a/packages/nextjs/components/dash-wind/features/settings/billing/index.tsx b/packages/nextjs/components/dash-wind/features/settings/billing/index.tsx new file mode 100644 index 0000000..77ad880 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/settings/billing/index.tsx @@ -0,0 +1,156 @@ +import { useState } from "react"; +import TitleCard from "../../../components/Cards/TitleCard"; +// import { showNotification } from "../../common/headerSlice"; +import moment from "moment"; + +// import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store"; + +const BILLS = [ + { + invoiceNo: "#4567", + amount: "23,989", + description: "Product usages", + status: "Pending", + generatedOn: moment(new Date()) + .add(-30 * 1, "days") + .format("DD MMM YYYY"), + paidOn: "-", + }, + + { + invoiceNo: "#4523", + amount: "34,989", + description: "Product usages", + status: "Pending", + generatedOn: moment(new Date()) + .add(-30 * 2, "days") + .format("DD MMM YYYY"), + paidOn: "-", + }, + + { + invoiceNo: "#4453", + amount: "39,989", + description: "Product usages", + status: "Paid", + generatedOn: moment(new Date()) + .add(-30 * 3, "days") + .format("DD MMM YYYY"), + paidOn: moment(new Date()) + .add(-24 * 2, "days") + .format("DD MMM YYYY"), + }, + + { + invoiceNo: "#4359", + amount: "28,927", + description: "Product usages", + status: "Paid", + generatedOn: moment(new Date()) + .add(-30 * 4, "days") + .format("DD MMM YYYY"), + paidOn: moment(new Date()) + .add(-24 * 3, "days") + .format("DD MMM YYYY"), + }, + + { + invoiceNo: "#3359", + amount: "28,927", + description: "Product usages", + status: "Paid", + generatedOn: moment(new Date()) + .add(-30 * 5, "days") + .format("DD MMM YYYY"), + paidOn: moment(new Date()) + .add(-24 * 4, "days") + .format("DD MMM YYYY"), + }, + + { + invoiceNo: "#3367", + amount: "28,927", + description: "Product usages", + status: "Paid", + generatedOn: moment(new Date()) + .add(-30 * 6, "days") + .format("DD MMM YYYY"), + paidOn: moment(new Date()) + .add(-24 * 5, "days") + .format("DD MMM YYYY"), + }, + + { + invoiceNo: "#3359", + amount: "28,927", + description: "Product usages", + status: "Paid", + generatedOn: moment(new Date()) + .add(-30 * 7, "days") + .format("DD MMM YYYY"), + paidOn: moment(new Date()) + .add(-24 * 6, "days") + .format("DD MMM YYYY"), + }, + + { + invoiceNo: "#2359", + amount: "28,927", + description: "Product usages", + status: "Paid", + generatedOn: moment(new Date()) + .add(-30 * 8, "days") + .format("DD MMM YYYY"), + paidOn: moment(new Date()) + .add(-24 * 7, "days") + .format("DD MMM YYYY"), + }, +]; + +function Billing() { + const [bills] = useState(BILLS); + + const getPaymentStatus = (status: string) => { + if (status === "Paid") return
{status}
; + if (status === "Pending") return
{status}
; + else return
{status}
; + }; + + return ( + <> + + {/* Invoice list in table format loaded constant */} +
+ + + + + + + + + + + + + {bills.map((l, k) => { + return ( + + + + + + + + + ); + })} + +
Invoice NoInvoice Generated OnDescriptionAmountStatusInvoice Paid On
{l.invoiceNo}{l.generatedOn}{l.description}${l.amount}{getPaymentStatus(l.status)}{l.paidOn}
+
+
+ + ); +} + +export default Billing; diff --git a/packages/nextjs/components/dash-wind/features/settings/profilesettings/index.tsx b/packages/nextjs/components/dash-wind/features/settings/profilesettings/index.tsx new file mode 100644 index 0000000..42b8d0c --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/settings/profilesettings/index.tsx @@ -0,0 +1,60 @@ +// import { useEffect, useState } from "react"; +import TitleCard from "../../../components/Cards/TitleCard"; +import InputText from "../../../components/Input/InputText"; +import TextAreaInput from "../../../components/Input/TextAreaInput"; +import ToggleInput from "../../../components/Input/ToggleInput"; +import { UpdateFormValues } from "../../../types/FormTypes"; +import { showNotification } from "../../common/headerSlice"; +// import moment from "moment"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function ProfileSettings() { + const dispatch = useMyDispatch(); + + // Call API to update profile settings changes + const updateProfile = () => { + dispatch(showNotification({ message: "Profile Updated", status: 1 })); + }; + + const updateFormValue = ({ updateType }: UpdateFormValues) => { + console.log(updateType); + }; + + return ( + <> + +
+ + + + + +
+
+ +
+ + + +
+ +
+ +
+
+ + ); +} + +export default ProfileSettings; diff --git a/packages/nextjs/components/dash-wind/features/settings/team/index.tsx b/packages/nextjs/components/dash-wind/features/settings/team/index.tsx new file mode 100644 index 0000000..d6b5360 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/settings/team/index.tsx @@ -0,0 +1,145 @@ +/* eslint-disable @next/next/no-img-element */ +import { useState } from "react"; +// import Image from "next/image"; +import TitleCard from "../../../components/Cards/TitleCard"; +import { showNotification } from "../../common/headerSlice"; +import moment from "moment"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +const TopSideButtons = () => { + const dispatch = useMyDispatch(); + + const addNewTeamMember = () => { + dispatch(showNotification({ message: "Add New Member clicked", status: 1 })); + }; + + return ( +
+ +
+ ); +}; + +const TEAM_MEMBERS = [ + { + name: "Alex", + avatar: "https://reqres.in/img/faces/1-image.jpg", + email: "alex@dashwind.com", + role: "Owner", + joinedOn: moment(new Date()) + .add(-5 * 1, "days") + .format("DD MMM YYYY"), + lastActive: "5 hr ago", + }, + { + name: "Ereena", + avatar: "https://reqres.in/img/faces/2-image.jpg", + email: "ereena@dashwind.com", + role: "Admin", + joinedOn: moment(new Date()) + .add(-5 * 2, "days") + .format("DD MMM YYYY"), + lastActive: "15 min ago", + }, + { + name: "John", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "jhon@dashwind.com", + role: "Admin", + joinedOn: moment(new Date()) + .add(-5 * 3, "days") + .format("DD MMM YYYY"), + lastActive: "20 hr ago", + }, + { + name: "Matrix", + avatar: "https://reqres.in/img/faces/4-image.jpg", + email: "matrix@dashwind.com", + role: "Manager", + joinedOn: moment(new Date()) + .add(-5 * 4, "days") + .format("DD MMM YYYY"), + lastActive: "1 hr ago", + }, + { + name: "Virat", + avatar: "https://reqres.in/img/faces/5-image.jpg", + email: "virat@dashwind.com", + role: "Support", + joinedOn: moment(new Date()) + .add(-5 * 5, "days") + .format("DD MMM YYYY"), + lastActive: "40 min ago", + }, + { + name: "Miya", + avatar: "https://reqres.in/img/faces/6-image.jpg", + email: "miya@dashwind.com", + role: "Support", + joinedOn: moment(new Date()) + .add(-5 * 7, "days") + .format("DD MMM YYYY"), + lastActive: "5 hr ago", + }, +]; + +function Team() { + const [members] = useState(TEAM_MEMBERS); + + const getRoleComponent = (role: string) => { + if (role === "Admin") return
{role}
; + if (role === "Manager") return
{role}
; + if (role === "Owner") return
{role}
; + if (role === "Support") return
{role}
; + else return
{role}
; + }; + + return ( + <> + }> + {/* Team Member list in table format loaded constant */} +
+ + + + + + + + + + + + {members.map((l, k) => { + return ( + + + + + + + + ); + })} + +
NameEmail IdJoined OnRoleLast Active
+
+
+
+ Avatar +
+
+
+
{l.name}
+
+
+
{l.email}{l.joinedOn}{getRoleComponent(l.role)}{l.lastActive}
+
+
+ + ); +} + +export default Team; diff --git a/packages/nextjs/components/dash-wind/features/transactions/index.tsx b/packages/nextjs/components/dash-wind/features/transactions/index.tsx new file mode 100644 index 0000000..955e780 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/transactions/index.tsx @@ -0,0 +1,149 @@ +/* eslint-disable @next/next/no-img-element */ +import { useCallback, useEffect, useState } from "react"; +// import Image from "next/image"; +import TitleCard from "../../components/Cards/TitleCard"; +import SearchBar from "../../components/Input/SearchBar"; +import { RECENT_TRANSACTIONS } from "../../utils/dummyData"; +// import { showNotification } from "../common/headerSlice"; +import moment from "moment"; +// import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store"; +import FunnelIcon from "@heroicons/react/24/outline/FunnelIcon"; +import XMarkIcon from "@heroicons/react/24/outline/XMarkIcon"; + +interface TopSideButtonsProps { + applySearch: (value: string) => void; + applyFilter: (params: string) => void; + removeFilter: () => void; +} + +const TopSideButtons = ({ removeFilter, applyFilter, applySearch }: TopSideButtonsProps) => { + const [filterParam, setFilterParam] = useState(""); + const [searchText, setSearchText] = useState(""); + const locationFilters = ["Paris", "London", "Canada", "Peru", "Tokyo"]; + + const showFiltersAndApply = (params: string) => { + applyFilter(params); + setFilterParam(params); + }; + + const removeAppliedFilter = useCallback(() => { + removeFilter(); + setFilterParam(""); + setSearchText(""); + }, [removeFilter]); + + useEffect(() => { + if (searchText == "") { + removeAppliedFilter(); + } else { + applySearch(searchText); + } + }, [applySearch, removeAppliedFilter, searchText]); + + return ( +
+ + {filterParam != "" && ( + + )} +
+ + +
+
+ ); +}; + +function Transactions() { + const [trans, setTrans] = useState(RECENT_TRANSACTIONS); + + const removeFilter = () => { + setTrans(RECENT_TRANSACTIONS); + }; + + const applyFilter = (params: string) => { + const filteredTransactions = RECENT_TRANSACTIONS.filter(t => { + return t.location == params; + }); + setTrans(filteredTransactions); + }; + + // Search according to name + const applySearch = (value: string) => { + const filteredTransactions = RECENT_TRANSACTIONS.filter(t => { + return t.email.toLowerCase().includes(value.toLowerCase()) || t.email.toLowerCase().includes(value.toLowerCase()); + }); + setTrans(filteredTransactions); + }; + + return ( + <> + + } + > + {/* Team Member list in table format loaded constant */} +
+ + + + + + + + + + + + {trans.map((l, k) => { + return ( + + + + + + + + ); + })} + +
NameEmail IdLocationAmountTransaction Date
+
+
+
+ Avatar +
+
+
+
{l.name}
+
+
+
{l.email}{l.location}${l.amount}{moment(l.date).format("D MMM")}
+
+
+ + ); +} + +export default Transactions; diff --git a/packages/nextjs/components/dash-wind/features/user/ForgotPassword.tsx b/packages/nextjs/components/dash-wind/features/user/ForgotPassword.tsx new file mode 100644 index 0000000..42a483d --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/user/ForgotPassword.tsx @@ -0,0 +1,100 @@ +import { useState } from "react"; +import Link from "next/link"; +import InputText from "../../components/Input/InputText"; +import ErrorText from "../../components/Typography/ErrorText"; +import { UpdateFormValues } from "../../types/FormTypes"; +import LandingIntro from "./LandingIntro"; +import CheckCircleIcon from "@heroicons/react/24/solid/CheckCircleIcon"; + +function ForgotPassword() { + const INITIAL_USER_OBJ = { + emailId: "", + }; + + const [loading, setLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState(""); + const [linkSent, setLinkSent] = useState(false); + const [userObj, setUserObj] = useState(INITIAL_USER_OBJ); + + const submitForm = (e: React.FormEvent) => { + e.preventDefault(); + setErrorMessage(""); + + if (userObj.emailId.trim() === "") return setErrorMessage("Email Id is required! (use any value)"); + else { + setLoading(true); + // Call API to send password reset link + setLoading(false); + setLinkSent(true); + } + }; + + const updateFormValue = ({ updateType, value }: UpdateFormValues) => { + setErrorMessage(""); + setUserObj({ ...userObj, [updateType]: value }); + }; + + return ( +
+
+
+
+ +
+
+

Forgot Password

+ + {linkSent && ( + <> +
+ +
+

Link Sent

+

Check your email to reset password

+
+ + + +
+ + )} + + {!linkSent && ( + <> +

We will send password reset link on your email Id

+
submitForm(e)}> +
+ +
+ + {errorMessage} + + +
+ Don't have an account yet?{" "} + + + +
+
+ + )} +
+
+
+
+ ); +} + +export default ForgotPassword; diff --git a/packages/nextjs/components/dash-wind/features/user/LandingIntro.tsx b/packages/nextjs/components/dash-wind/features/user/LandingIntro.tsx new file mode 100644 index 0000000..0356366 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/user/LandingIntro.tsx @@ -0,0 +1,27 @@ +/* eslint-disable @next/next/no-img-element */ +// import Image from "next/image"; +import TemplatePointers from "./components/TemplatePointers"; + +function LandingIntro() { + return ( +
+
+
+

+ dashwind-logo + DashWind +

+ +
+ Dashwind Admin Template +
+ + {/* Importing pointers component */} + +
+
+
+ ); +} + +export default LandingIntro; diff --git a/packages/nextjs/components/dash-wind/features/user/Login.tsx b/packages/nextjs/components/dash-wind/features/user/Login.tsx new file mode 100644 index 0000000..9ce5ef6 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/user/Login.tsx @@ -0,0 +1,97 @@ +import { useState } from "react"; +import Link from "next/link"; +import InputText from "../../components/Input/InputText"; +import ErrorText from "../../components/Typography/ErrorText"; +import { UpdateFormValues } from "../../types/FormTypes"; +import LandingIntro from "./LandingIntro"; + +function Login() { + const INITIAL_LOGIN_OBJ = { + password: "", + emailId: "", + }; + + const [loading, setLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState(""); + const [loginObj, setLoginObj] = useState(INITIAL_LOGIN_OBJ); + + const submitForm = (e: React.FormEvent) => { + e.preventDefault(); + setErrorMessage(""); + + if (loginObj.emailId.trim() === "") return setErrorMessage("Email Id is required! (use any value)"); + if (loginObj.password.trim() === "") return setErrorMessage("Password is required! (use any value)"); + else { + setLoading(true); + // Call API to check user credentials and save token in localstorage + localStorage.setItem("token", "DumyTokenHere"); + setLoading(false); + window.location.href = "/dapp/welcome"; + } + }; + + const updateFormValue = ({ updateType, value }: UpdateFormValues) => { + setErrorMessage(""); + setLoginObj({ ...loginObj, [updateType]: value }); + }; + + return ( +
+
+
+
+ +
+
+

Login

+
submitForm(e)}> +
+ + + +
+ +
+ + + Forgot Password? + + +
+ + {errorMessage} + + +
+ Don't have an account yet?{" "} + + + Register + + +
+
+
+
+
+
+ ); +} + +export default Login; diff --git a/packages/nextjs/components/dash-wind/features/user/Register.tsx b/packages/nextjs/components/dash-wind/features/user/Register.tsx new file mode 100644 index 0000000..7496f5b --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/user/Register.tsx @@ -0,0 +1,98 @@ +import { useState } from "react"; +import Link from "next/link"; +import InputText from "../../components/Input/InputText"; +import ErrorText from "../../components/Typography/ErrorText"; +import { UpdateFormValues } from "../../types/FormTypes"; +import LandingIntro from "./LandingIntro"; + +function Register() { + const INITIAL_REGISTER_OBJ = { + name: "", + password: "", + emailId: "", + }; + + const [loading, setLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState(""); + const [registerObj, setRegisterObj] = useState(INITIAL_REGISTER_OBJ); + + const submitForm = (e: React.FormEvent) => { + e.preventDefault(); + setErrorMessage(""); + + if (registerObj.name.trim() === "") return setErrorMessage("Name is required! (use any value)"); + if (registerObj.emailId.trim() === "") return setErrorMessage("Email Id is required! (use any value)"); + if (registerObj.password.trim() === "") return setErrorMessage("Password is required! (use any value)"); + else { + setLoading(true); + // Call API to check user credentials and save token in localstorage + localStorage.setItem("token", "DumyTokenHere"); + setLoading(false); + window.location.href = "/dapp/welcome"; + } + }; + + const updateFormValue = ({ updateType, value }: UpdateFormValues) => { + setErrorMessage(""); + setRegisterObj({ ...registerObj, [updateType]: value }); + }; + + return ( +
+
+
+
+ +
+
+

Register

+
submitForm(e)}> +
+ + + + + +
+ + {errorMessage} + + +
+ Already have an account?{" "} + + + Login + + +
+
+
+
+
+
+ ); +} + +export default Register; diff --git a/packages/nextjs/components/dash-wind/features/user/components/TemplatePointers.tsx b/packages/nextjs/components/dash-wind/features/user/components/TemplatePointers.tsx new file mode 100644 index 0000000..c28fc68 --- /dev/null +++ b/packages/nextjs/components/dash-wind/features/user/components/TemplatePointers.tsx @@ -0,0 +1,25 @@ +function TemplatePointers() { + return ( + <> +

Admin Dashboard Starter Kit

+

+ ✓ Light/dark mode toggle +

+

+ ✓ Redux toolkit and other utility libraries configured +

+

+ ✓ Calendar, Modal, Sidebar components +

+

+ ✓ User-friendly documentation +

+

+ ✓ Daisy UI components,{" "} + Tailwind CSS support +

+ + ); +} + +export default TemplatePointers; diff --git a/packages/nextjs/components/dash-wind/pages/DocComponents.js b/packages/nextjs/components/dash-wind/pages/DocComponents.js new file mode 100644 index 0000000..bc0bce4 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/DocComponents.js @@ -0,0 +1,11 @@ +import DocComponents from "../features/documentation/DocComponents"; + +function ExternalPage() { + return ( +
+ +
+ ); +} + +export default ExternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/DocFeatures.tsx b/packages/nextjs/components/dash-wind/pages/DocFeatures.tsx new file mode 100644 index 0000000..ea974c1 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/DocFeatures.tsx @@ -0,0 +1,11 @@ +// import DocFeatures from "../features/documentation/DocFeatures"; + +// function ExternalPage() { +// return ( +//
+// +//
+// ); +// } + +// export default ExternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/Documentation.js b/packages/nextjs/components/dash-wind/pages/Documentation.js new file mode 100644 index 0000000..e0e33d8 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/Documentation.js @@ -0,0 +1,40 @@ +import DocComponentsContent from "../features/documentation/components/DocComponentsContent"; +import DocComponentsNav from "../features/documentation/components/DocComponentsNav"; +import FeaturesContent from "../features/documentation/components/FeaturesContent"; +import FeaturesNav from "../features/documentation/components/FeaturesNav"; +import GettingStartedContent from "../features/documentation/components/GettingStartedContent"; +import GettingStartedNav from "../features/documentation/components/GettingStartedNav"; +import { Link } from "react-router-dom"; + +function Documentation() { + return ( + <> +
+
+
+
+

Dashwind

+ + + + + + + +
+ +
+ + + +
+
+
+
+ + ); +} + +export default Documentation; diff --git a/packages/nextjs/components/dash-wind/pages/ForgotPassword.tsx b/packages/nextjs/components/dash-wind/pages/ForgotPassword.tsx new file mode 100644 index 0000000..2ba6767 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/ForgotPassword.tsx @@ -0,0 +1,11 @@ +import ForgotPassword from "../features/user/ForgotPassword"; + +function ExternalPage() { + return ( +
+ +
+ ); +} + +export default ExternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/GettingStarted.js b/packages/nextjs/components/dash-wind/pages/GettingStarted.js new file mode 100644 index 0000000..77ff231 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/GettingStarted.js @@ -0,0 +1,12 @@ +// import DocGettingStarted from "../features/documentation/DocGettingStarted"; + +function ExternalPage() { + return ( +
+ This is the documentation component - no need to convert + {/* */} +
+ ); +} + +export default ExternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/Login.tsx b/packages/nextjs/components/dash-wind/pages/Login.tsx new file mode 100644 index 0000000..1f93a5c --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/Login.tsx @@ -0,0 +1,11 @@ +import Login from "../features/user/Login"; + +function ExternalPage() { + return ( +
+ +
+ ); +} + +export default ExternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/Register.tsx b/packages/nextjs/components/dash-wind/pages/Register.tsx new file mode 100644 index 0000000..6442362 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/Register.tsx @@ -0,0 +1,11 @@ +import Register from "../features/user/Register"; + +function ExternalPage() { + return ( +
+ +
+ ); +} + +export default ExternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Bills.tsx b/packages/nextjs/components/dash-wind/pages/protected/Bills.tsx new file mode 100644 index 0000000..da34068 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Bills.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import Billing from "../../features/settings/billing"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Bills" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Blank.tsx b/packages/nextjs/components/dash-wind/pages/protected/Blank.tsx new file mode 100644 index 0000000..e795fcc --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Blank.tsx @@ -0,0 +1,25 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import DocumentIcon from "@heroicons/react/24/solid/DocumentIcon"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Page Title" })); + }, [dispatch]); + + return ( +
+
+
+ +

Blank Page

+
+
+
+ ); +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Calendar.tsx b/packages/nextjs/components/dash-wind/pages/protected/Calendar.tsx new file mode 100644 index 0000000..208593e --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Calendar.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import Calendar from "../../features/calendar"; +import { setPageTitle } from "../../features/common/headerSlice"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Calendar" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Charts.tsx b/packages/nextjs/components/dash-wind/pages/protected/Charts.tsx new file mode 100644 index 0000000..3d6e7be --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Charts.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import Charts from "../../features/charts"; +import { setPageTitle } from "../../features/common/headerSlice"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Analytics" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Dashboard.tsx b/packages/nextjs/components/dash-wind/pages/protected/Dashboard.tsx new file mode 100644 index 0000000..b1a5ce6 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Dashboard.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import Dashboard from "../../features/dashboard/index"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Dashboard" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Integration.tsx b/packages/nextjs/components/dash-wind/pages/protected/Integration.tsx new file mode 100644 index 0000000..3bc2bdc --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Integration.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import Integration from "../../features/integration"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Integrations" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Leads.tsx b/packages/nextjs/components/dash-wind/pages/protected/Leads.tsx new file mode 100644 index 0000000..97c8723 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Leads.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import Leads from "../../features/leads"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Leads" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/ProfileSettings.tsx b/packages/nextjs/components/dash-wind/pages/protected/ProfileSettings.tsx new file mode 100644 index 0000000..8c280b9 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/ProfileSettings.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import ProfileSettings from "../../features/settings/profilesettings"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Settings" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Team.tsx b/packages/nextjs/components/dash-wind/pages/protected/Team.tsx new file mode 100644 index 0000000..5e10bd3 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Team.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import Team from "../../features/settings/team"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Team Members" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Transactions.tsx b/packages/nextjs/components/dash-wind/pages/protected/Transactions.tsx new file mode 100644 index 0000000..1fcdb58 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Transactions.tsx @@ -0,0 +1,16 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import Transactions from "../../features/transactions"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "Transactions" })); + }, [dispatch]); + + return ; +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/Welcome.tsx b/packages/nextjs/components/dash-wind/pages/protected/Welcome.tsx new file mode 100644 index 0000000..c565a6d --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/Welcome.tsx @@ -0,0 +1,28 @@ +import { useEffect } from "react"; +import Link from "next/link"; +import { setPageTitle } from "../../features/common/headerSlice"; +import TemplatePointers from "../../features/user/components/TemplatePointers"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "" })); + }, [dispatch]); + + return ( +
+
+
+ + + + +
+
+
+ ); +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/pages/protected/_404.tsx b/packages/nextjs/components/dash-wind/pages/protected/_404.tsx new file mode 100644 index 0000000..1f74c03 --- /dev/null +++ b/packages/nextjs/components/dash-wind/pages/protected/_404.tsx @@ -0,0 +1,25 @@ +import { useEffect } from "react"; +import { setPageTitle } from "../../features/common/headerSlice"; +import FaceFrownIcon from "@heroicons/react/24/solid/FaceFrownIcon"; +import { useMyDispatch } from "~~/components/dash-wind/app/store"; + +function InternalPage() { + const dispatch = useMyDispatch(); + + useEffect(() => { + dispatch(setPageTitle({ title: "" })); + }, [dispatch]); + + return ( +
+
+
+ +

404 - Not Found

+
+
+
+ ); +} + +export default InternalPage; diff --git a/packages/nextjs/components/dash-wind/routes/index.ts b/packages/nextjs/components/dash-wind/routes/index.ts new file mode 100644 index 0000000..b050328 --- /dev/null +++ b/packages/nextjs/components/dash-wind/routes/index.ts @@ -0,0 +1,83 @@ +// All components mapping with path for internal routes +import { lazy } from "react"; + +const Dashboard = lazy(() => import("../pages/protected/Dashboard")); +const Welcome = lazy(() => import("../pages/protected/Welcome")); +const Page404 = lazy(() => import("../pages/protected/_404")); +const Blank = lazy(() => import("../pages/protected/Blank")); +const Charts = lazy(() => import("../pages/protected/Charts")); +const Leads = lazy(() => import("../pages/protected/Leads")); +const Integration = lazy(() => import("../pages/protected/Integration")); +const Calendar = lazy(() => import("../pages/protected/Calendar")); +const Team = lazy(() => import("../pages/protected/Team")); +const Transactions = lazy(() => import("../pages/protected/Transactions")); +const Bills = lazy(() => import("../pages/protected/Bills")); +const ProfileSettings = lazy(() => import("../pages/protected/ProfileSettings")); +const GettingStarted = lazy(() => import("../pages/GettingStarted")); +// const DocFeatures = lazy(() => import("../pages/DocFeatures")); +const DocComponents = lazy(() => import("../pages/DocComponents")); + +const routes = [ + { + path: "/dashboard", // the url + component: Dashboard, // view rendered + }, + { + path: "/welcome", // the url + component: Welcome, // view rendered + }, + { + path: "/leads", + component: Leads, + }, + { + path: "/settings-team", + component: Team, + }, + { + path: "/calendar", + component: Calendar, + }, + { + path: "/transactions", + component: Transactions, + }, + { + path: "/settings-profile", + component: ProfileSettings, + }, + { + path: "/settings-billing", + component: Bills, + }, + { + path: "/getting-started", + component: GettingStarted, + }, + // { + // path: "/features", + // component: DocFeatures, + // }, + { + path: "/components", + component: DocComponents, + }, + { + path: "/integration", + component: Integration, + }, + { + path: "/charts", + component: Charts, + }, + { + path: "/404", + component: Page404, + }, + { + path: "/blank", + component: Blank, + }, +]; + +export default routes; diff --git a/packages/nextjs/components/dash-wind/routes/sidebar.ts b/packages/nextjs/components/dash-wind/routes/sidebar.ts new file mode 100644 index 0000000..026e758 --- /dev/null +++ b/packages/nextjs/components/dash-wind/routes/sidebar.ts @@ -0,0 +1,155 @@ +/** Icons are imported separatly to reduce build time */ +// import ArrowRightOnRectangleIcon from "@heroicons/react/24/outline/ArrowRightOnRectangleIcon"; +// import BellIcon from "@heroicons/react/24/outline/BellIcon"; +import BoltIcon from "@heroicons/react/24/outline/BoltIcon"; +import CalendarDaysIcon from "@heroicons/react/24/outline/CalendarDaysIcon"; +import ChartBarIcon from "@heroicons/react/24/outline/ChartBarIcon"; +// import CodeBracketSquareIcon from "@heroicons/react/24/outline/CodeBracketSquareIcon"; +import Cog6ToothIcon from "@heroicons/react/24/outline/Cog6ToothIcon"; +import CurrencyDollarIcon from "@heroicons/react/24/outline/CurrencyDollarIcon"; +// import DocumentDuplicateIcon from "@heroicons/react/24/outline/DocumentDuplicateIcon"; +// import DocumentIcon from "@heroicons/react/24/outline/DocumentIcon"; +// import DocumentTextIcon from "@heroicons/react/24/outline/DocumentTextIcon"; +// import ExclamationTriangleIcon from "@heroicons/react/24/outline/ExclamationTriangleIcon"; +import InboxArrowDownIcon from "@heroicons/react/24/outline/InboxArrowDownIcon"; +// import KeyIcon from "@heroicons/react/24/outline/KeyIcon"; +import Squares2X2Icon from "@heroicons/react/24/outline/Squares2X2Icon"; +// import TableCellsIcon from "@heroicons/react/24/outline/TableCellsIcon"; +import UserIcon from "@heroicons/react/24/outline/UserIcon"; +import UsersIcon from "@heroicons/react/24/outline/UsersIcon"; +import WalletIcon from "@heroicons/react/24/outline/WalletIcon"; + +const iconClasses = `h-6 w-6`; +const submenuIconClasses = `h-5 w-5`; + +const routes = [ + { + path: "/dapp/dashboard", + icon: Squares2X2Icon, + className: iconClasses, + name: "Dashboard", + }, + { + path: "/dapp/leads", // url + icon: InboxArrowDownIcon, // icon component + className: iconClasses, + name: "Leads", // name that appear in Sidebar + }, + { + path: "/dapp/transactions", // url + icon: CurrencyDollarIcon, // icon component + className: iconClasses, + name: "Transactions", // name that appear in Sidebar + }, + { + path: "/dapp/charts", // url + icon: ChartBarIcon, // icon component + className: iconClasses, + name: "Analytics", // name that appear in Sidebar + }, + { + path: "/dapp/integration", // url + icon: BoltIcon, // icon component + className: iconClasses, + name: "Integration", // name that appear in Sidebar + }, + { + path: "/dapp/calendar", // url + icon: CalendarDaysIcon, // icon component + className: iconClasses, + name: "Calendar", // name that appear in Sidebar + }, + + // { + // path: "", //no url needed as this has submenu + // icon: DocumentDuplicateIcon, // icon component + // className: `${iconClasses} inline`, + // name: "Pages", // name that appear in Sidebar + // submenu: [ + // { + // path: "/login", + // icon: ArrowRightOnRectangleIcon, + // className: submenuIconClasses, + // name: "Login", + // }, + // { + // path: "/register", //url + // icon: UserIcon, // icon component + // className: submenuIconClasses, + // name: "Register", // name that appear in Sidebar + // }, + // { + // path: "/forgot-password", + // icon: KeyIcon, + // className: submenuIconClasses, + // name: "Forgot Password", + // }, + // { + // path: "/dapp/blank", + // icon: DocumentIcon, + // className: submenuIconClasses, + // name: "Blank Page", + // }, + // { + // path: "/dapp/404", + // icon: ExclamationTriangleIcon, + // className: submenuIconClasses, + // name: "404", + // }, + // ], + // }, + { + path: "", //no url needed as this has submenu + icon: Cog6ToothIcon, // icon component + className: `${iconClasses} inline`, + name: "Settings", // name that appear in Sidebar + submenu: [ + { + path: "/dapp/settings-profile", //url + icon: UserIcon, // icon component + className: submenuIconClasses, + name: "Profile", // name that appear in Sidebar + }, + { + path: "/dapp/settings-billing", + icon: WalletIcon, + className: submenuIconClasses, + name: "Billing", + }, + { + path: "/dapp/settings-team", // url + icon: UsersIcon, // icon component + className: submenuIconClasses, + name: "Team Members", // name that appear in Sidebar + }, + ], + }, + // { + // path: "", //no url needed as this has submenu + // icon: DocumentTextIcon, // icon component + // className: `${iconClasses} inline`, + // name: "Documentation", // name that appear in Sidebar + // submenu: [ + // { + // path: "/dapp/getting-started", // url + // icon: DocumentTextIcon, // icon component + // className: submenuIconClasses, + // name: "Getting Started", // name that appear in Sidebar + // }, + // { + // path: "/dapp/features", + // icon: TableCellsIcon, + // className: submenuIconClasses, + // name: "Features", + // }, + // { + // path: "/dapp/components", + // icon: CodeBracketSquareIcon, + // className: submenuIconClasses, + // name: "Components", + // }, + // ], + // }, +]; + +export default routes; diff --git a/packages/nextjs/components/dash-wind/types/CalendarTypes.ts b/packages/nextjs/components/dash-wind/types/CalendarTypes.ts new file mode 100644 index 0000000..a7a281a --- /dev/null +++ b/packages/nextjs/components/dash-wind/types/CalendarTypes.ts @@ -0,0 +1,18 @@ +export type CalendarEvent = { + title: string; + theme: string; + startTime: any; + endTime: any; +}; + +export type CalendarMore = { + title: string; + theme: string; +}; + +export type CalendarDetails = { + filteredEvents: CalendarMore[]; + title: string; +}; + +export type CalendarEvents = (CalendarEvent | CalendarMore)[]; diff --git a/packages/nextjs/components/dash-wind/types/DateTypes.ts b/packages/nextjs/components/dash-wind/types/DateTypes.ts new file mode 100644 index 0000000..bb39852 --- /dev/null +++ b/packages/nextjs/components/dash-wind/types/DateTypes.ts @@ -0,0 +1,6 @@ +import { DateType } from "react-tailwindcss-datepicker"; + +export interface DateValue { + startDate: DateType; + endDate: DateType; +} diff --git a/packages/nextjs/components/dash-wind/types/FormTypes.ts b/packages/nextjs/components/dash-wind/types/FormTypes.ts new file mode 100644 index 0000000..fdd9c83 --- /dev/null +++ b/packages/nextjs/components/dash-wind/types/FormTypes.ts @@ -0,0 +1,4 @@ +export interface UpdateFormValues { + updateType: string; + value: string; +} diff --git a/packages/nextjs/components/dash-wind/types/InputTextTypes.ts b/packages/nextjs/components/dash-wind/types/InputTextTypes.ts new file mode 100644 index 0000000..cece698 --- /dev/null +++ b/packages/nextjs/components/dash-wind/types/InputTextTypes.ts @@ -0,0 +1,20 @@ +export interface REGISTER_OBJ { + name: ""; + password: ""; + emailId: ""; +} + +export interface LOGIN_OBJ { + password: ""; + emailId: ""; +} + +export interface USER_OBJ { + emailId: ""; +} + +export interface LEAD_OBJ { + first_name: ""; + last_name: ""; + email: ""; +} diff --git a/packages/nextjs/components/dash-wind/types/declarations.d.ts b/packages/nextjs/components/dash-wind/types/declarations.d.ts new file mode 100644 index 0000000..053b857 --- /dev/null +++ b/packages/nextjs/components/dash-wind/types/declarations.d.ts @@ -0,0 +1 @@ +declare module "react-notifications"; diff --git a/packages/nextjs/components/dash-wind/utils/dummyData.ts b/packages/nextjs/components/dash-wind/utils/dummyData.ts new file mode 100644 index 0000000..3235cb3 --- /dev/null +++ b/packages/nextjs/components/dash-wind/utils/dummyData.ts @@ -0,0 +1,227 @@ +import moment from "moment"; + +export const CALENDAR_INITIAL_EVENTS = [ + { + title: "Product call", + theme: "GREEN", + startTime: moment().add(-12, "d").startOf("day"), + endTime: moment().add(-12, "d").endOf("day"), + }, + { + title: "Meeting with tech team", + theme: "PINK", + startTime: moment().add(-8, "d").startOf("day"), + endTime: moment().add(-8, "d").endOf("day"), + }, + { + title: "Meeting with Cristina", + theme: "PURPLE", + startTime: moment().add(-2, "d").startOf("day"), + endTime: moment().add(-2, "d").endOf("day"), + }, + { title: "Meeting with Alex", theme: "BLUE", startTime: moment().startOf("day"), endTime: moment().endOf("day") }, + { title: "Product Call", theme: "GREEN", startTime: moment().startOf("day"), endTime: moment().endOf("day") }, + { title: "Client Meeting", theme: "PURPLE", startTime: moment().startOf("day"), endTime: moment().endOf("day") }, + { + title: "Client Meeting", + theme: "ORANGE", + startTime: moment().add(3, "d").startOf("day"), + endTime: moment().add(3, "d").endOf("day"), + }, + { + title: "Product meeting", + theme: "PINK", + startTime: moment().add(5, "d").startOf("day"), + endTime: moment().add(5, "d").endOf("day"), + }, + { + title: "Sales Meeting", + theme: "GREEN", + startTime: moment().add(8, "d").startOf("day"), + endTime: moment().add(8, "d").endOf("day"), + }, + { + title: "Product Meeting", + theme: "ORANGE", + startTime: moment().add(8, "d").startOf("day"), + endTime: moment().add(8, "d").endOf("day"), + }, + { + title: "Marketing Meeting", + theme: "PINK", + startTime: moment().add(8, "d").startOf("day"), + endTime: moment().add(8, "d").endOf("day"), + }, + { + title: "Client Meeting", + theme: "GREEN", + startTime: moment().add(8, "d").startOf("day"), + endTime: moment().add(8, "d").endOf("day"), + }, + { + title: "Sales meeting", + theme: "BLUE", + startTime: moment().add(12, "d").startOf("day"), + endTime: moment().add(12, "d").endOf("day"), + }, + { + title: "Client meeting", + theme: "PURPLE", + startTime: moment().add(16, "d").startOf("day"), + endTime: moment().add(16, "d").endOf("day"), + }, +]; +export const RECENT_TRANSACTIONS = [ + { + name: "Alex", + avatar: "https://reqres.in/img/faces/1-image.jpg", + email: "alex@dashwind.com", + location: "Paris", + amount: 100, + date: moment().endOf("day"), + }, + { + name: "Ereena", + avatar: "https://reqres.in/img/faces/2-image.jpg", + email: "ereena@dashwind.com", + location: "London", + amount: 190, + date: moment().add(-1, "d").endOf("day"), + }, + { + name: "John", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "jhon@dashwind.com", + location: "Canada", + amount: 112, + date: moment().add(-1, "d").endOf("day"), + }, + { + name: "Matrix", + avatar: "https://reqres.in/img/faces/4-image.jpg", + email: "matrix@dashwind.com", + location: "Peru", + amount: 111, + date: moment().add(-1, "d").endOf("day"), + }, + { + name: "Virat", + avatar: "https://reqres.in/img/faces/5-image.jpg", + email: "virat@dashwind.com", + location: "London", + amount: 190, + date: moment().add(-2, "d").endOf("day"), + }, + { + name: "Miya", + avatar: "https://reqres.in/img/faces/6-image.jpg", + email: "miya@dashwind.com", + location: "Paris", + amount: 230, + date: moment().add(-2, "d").endOf("day"), + }, + { + name: "Virat", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "virat@dashwind.com", + location: "Canada", + amount: 331, + date: moment().add(-2, "d").endOf("day"), + }, + { + name: "Matrix", + avatar: "https://reqres.in/img/faces/1-image.jpg", + email: "matrix@dashwind.com", + location: "London", + amount: 581, + date: moment().add(-2, "d").endOf("day"), + }, + { + name: "Ereena", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "ereena@dashwind.com", + location: "Tokyo", + amount: 151, + date: moment().add(-2, "d").endOf("day"), + }, + { + name: "John", + avatar: "https://reqres.in/img/faces/2-image.jpg", + email: "jhon@dashwind.com", + location: "Paris", + amount: 91, + date: moment().add(-2, "d").endOf("day"), + }, + { + name: "Virat", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "virat@dashwind.com", + location: "Canada", + amount: 161, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "Matrix", + avatar: "https://reqres.in/img/faces/4-image.jpg", + email: "matrix@dashwind.com", + location: "US", + amount: 121, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "Ereena", + avatar: "https://reqres.in/img/faces/6-image.jpg", + email: "jhon@dashwind.com", + location: "Tokyo", + amount: 713, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "John", + avatar: "https://reqres.in/img/faces/2-image.jpg", + email: "ereena@dashwind.com", + location: "London", + amount: 217, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "Virat", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "virat@dashwind.com", + location: "Paris", + amount: 117, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "Miya", + avatar: "https://reqres.in/img/faces/7-image.jpg", + email: "jhon@dashwind.com", + location: "Canada", + amount: 612, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "Matrix", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "matrix@dashwind.com", + location: "London", + amount: 631, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "Virat", + avatar: "https://reqres.in/img/faces/2-image.jpg", + email: "ereena@dashwind.com", + location: "Tokyo", + amount: 151, + date: moment().add(-3, "d").endOf("day"), + }, + { + name: "Ereena", + avatar: "https://reqres.in/img/faces/3-image.jpg", + email: "virat@dashwind.com", + location: "Paris", + amount: 617, + date: moment().add(-3, "d").endOf("day"), + }, +]; diff --git a/packages/nextjs/components/dash-wind/utils/globalConstantUtil.ts b/packages/nextjs/components/dash-wind/utils/globalConstantUtil.ts new file mode 100644 index 0000000..c35c340 --- /dev/null +++ b/packages/nextjs/components/dash-wind/utils/globalConstantUtil.ts @@ -0,0 +1,16 @@ +export const MODAL_BODY_TYPES = Object.freeze({ + USER_DETAIL: "USER_DETAIL", + LEAD_ADD_NEW: "LEAD_ADD_NEW", + CONFIRMATION: "CONFIRMATION", + DEFAULT: "", +}); + +export const RIGHT_DRAWER_TYPES = Object.freeze({ + NOTIFICATION: "NOTIFICATION", + CALENDAR_EVENTS: "CALENDAR_EVENTS", + DEFAULT: "", +}); + +export const CONFIRMATION_MODAL_CLOSE_TYPES = Object.freeze({ + LEAD_DELETE: "LEAD_DELETE", +}); diff --git a/packages/nextjs/components/layouts/DashLayout.tsx b/packages/nextjs/components/layouts/DashLayout.tsx new file mode 100644 index 0000000..3d415bc --- /dev/null +++ b/packages/nextjs/components/layouts/DashLayout.tsx @@ -0,0 +1,49 @@ +import { useEffect } from "react"; +import React, { ReactNode } from "react"; +// import dynamic from "next/dynamic"; +import PageContent from "../dash-wind/containers/PageContent"; +import { NotificationContainer, NotificationManager } from "react-notifications"; +import "react-notifications/lib/notifications.css"; +import { MyState, useMyDispatch, useMySelector } from "~~/components/dash-wind/app/store"; +import LeftSidebar from "~~/components/dash-wind/containers/LeftSidebar"; +import ModalLayout from "~~/components/dash-wind/containers/ModalLayout"; +import RightSidebar from "~~/components/dash-wind/containers/RightSidebar"; +import { removeNotificationMessage } from "~~/components/dash-wind/features/common/headerSlice"; + +interface DashLayoutProps { + children: ReactNode; +} + +export default function DashLayout({ children }: DashLayoutProps) { + 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) */} +
+ + {children} + +
+ + {/* Right drawer - containing secondary content like notifications list etc.. */} + + + {/** Notification layout container */} + + + {/* Modal layout container */} + +
+ + ); +} diff --git a/packages/nextjs/components/web-3-crew/ExistingOrNewMember.tsx b/packages/nextjs/components/web-3-crew/ExistingOrNewMember.tsx index 60f5f15..909dce0 100644 --- a/packages/nextjs/components/web-3-crew/ExistingOrNewMember.tsx +++ b/packages/nextjs/components/web-3-crew/ExistingOrNewMember.tsx @@ -1,4 +1,4 @@ -import { FormSteps } from "~~/pages/dapp"; +import { FormSteps } from "~~/components/web-3-crew/types/FormSteps"; interface props { updateFormState: (value: FormSteps) => void; diff --git a/packages/nextjs/components/web-3-crew/LoginEmailOrWallet.tsx b/packages/nextjs/components/web-3-crew/LoginEmailOrWallet.tsx index b01001b..ad8082e 100644 --- a/packages/nextjs/components/web-3-crew/LoginEmailOrWallet.tsx +++ b/packages/nextjs/components/web-3-crew/LoginEmailOrWallet.tsx @@ -1,5 +1,5 @@ import BackButton from "./buttons/BackButton"; -import { FormSteps } from "~~/pages/dapp"; +import { FormSteps } from "~~/components/web-3-crew/types/FormSteps"; interface props { updateFormState: (value: FormSteps) => void; diff --git a/packages/nextjs/components/web-3-crew/RegisterCompanyOrEmployee.tsx b/packages/nextjs/components/web-3-crew/RegisterCompanyOrEmployee.tsx index b376a34..4062994 100644 --- a/packages/nextjs/components/web-3-crew/RegisterCompanyOrEmployee.tsx +++ b/packages/nextjs/components/web-3-crew/RegisterCompanyOrEmployee.tsx @@ -1,5 +1,5 @@ import BackButton from "./buttons/BackButton"; -import { FormSteps } from "~~/pages/dapp"; +import { FormSteps } from "~~/components/web-3-crew/types/FormSteps"; interface props { updateFormState: (value: FormSteps) => void; diff --git a/packages/nextjs/components/web-3-crew/buttons/BackButton.tsx b/packages/nextjs/components/web-3-crew/buttons/BackButton.tsx index 110a725..4601ea8 100644 --- a/packages/nextjs/components/web-3-crew/buttons/BackButton.tsx +++ b/packages/nextjs/components/web-3-crew/buttons/BackButton.tsx @@ -1,4 +1,4 @@ -import { FormSteps } from "~~/pages/dapp"; +import { FormSteps } from "~~/components/web-3-crew/types/FormSteps"; interface props { updateFormState: (value: FormSteps) => void; diff --git a/packages/nextjs/components/web-3-crew/forms/RegisterCompanyForm.tsx b/packages/nextjs/components/web-3-crew/forms/RegisterCompanyForm.tsx index 5af45a3..da03566 100644 --- a/packages/nextjs/components/web-3-crew/forms/RegisterCompanyForm.tsx +++ b/packages/nextjs/components/web-3-crew/forms/RegisterCompanyForm.tsx @@ -1,6 +1,6 @@ import { FormEvent } from "react"; import BackButton from "../buttons/BackButton"; -import { FormSteps } from "~~/pages/dapp"; +import { FormSteps } from "~~/components/web-3-crew/types/FormSteps"; interface props { updateFormState: (value: FormSteps) => void; @@ -67,7 +67,7 @@ const RegisterCompanyForm = ({ updateFormState }: props) => {
- diff --git a/packages/nextjs/components/web-3-crew/forms/RegisterEmployeeForm.tsx b/packages/nextjs/components/web-3-crew/forms/RegisterEmployeeForm.tsx index a0cc5c4..6b03876 100644 --- a/packages/nextjs/components/web-3-crew/forms/RegisterEmployeeForm.tsx +++ b/packages/nextjs/components/web-3-crew/forms/RegisterEmployeeForm.tsx @@ -1,6 +1,6 @@ import { FormEvent } from "react"; import BackButton from "../buttons/BackButton"; -import { FormSteps } from "~~/pages/dapp"; +import { FormSteps } from "~~/components/web-3-crew/types/FormSteps"; interface props { updateFormState: (value: FormSteps) => void; @@ -60,7 +60,7 @@ const RegisterEmployeeForm = ({ updateFormState }: props) => {
*/} - diff --git a/packages/nextjs/components/web-3-crew/types/FormSteps.ts b/packages/nextjs/components/web-3-crew/types/FormSteps.ts new file mode 100644 index 0000000..ef6b342 --- /dev/null +++ b/packages/nextjs/components/web-3-crew/types/FormSteps.ts @@ -0,0 +1 @@ +export type FormSteps = "start" | "login" | "signup" | "register-company" | "register-employee"; diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 17feb45..181d699 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -17,17 +17,28 @@ "@ethersproject/providers": "^5.7.2", "@heroicons/react": "^2.0.11", "@rainbow-me/rainbowkit": "1.1.2", + "@reduxjs/toolkit": "^1.9.7", "@uniswap/sdk-core": "^4.0.1", "@uniswap/v2-sdk": "^3.0.1", + "axios": "^1.6.2", "blo": "^1.0.1", + "chart.js": "^4.4.0", "daisyui": "^3.5.1", + "dayjs": "1.11.6", + "moment": "^2.29.4", "next": "^13.1.6", + "next-redux-wrapper": "^8.1.0", "nextjs-progressbar": "^0.0.16", "qrcode.react": "^3.1.0", "react": "^18.2.0", + "react-chartjs-2": "^5.2.0", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.2.0", "react-hot-toast": "^2.4.0", + "react-notifications": "^1.7.4", + "react-redux": "^8.1.3", + "react-tailwindcss-datepicker": "^1.6.6", + "theme-change": "^2.5.0", "use-debounce": "^8.0.4", "usehooks-ts": "^2.7.2", "viem": "^1.16.6", diff --git a/packages/nextjs/pages/404.tsx b/packages/nextjs/pages/404.tsx new file mode 100644 index 0000000..e9f09fc --- /dev/null +++ b/packages/nextjs/pages/404.tsx @@ -0,0 +1,9 @@ +import React, { lazy } from "react"; + +const Page404 = lazy(() => import("~~/components/dash-wind/pages/protected/_404")); + +function fourOhFour() { + return ; +} + +export default fourOhFour; diff --git a/packages/nextjs/pages/_app.tsx b/packages/nextjs/pages/_app.tsx index f083134..4c1a210 100644 --- a/packages/nextjs/pages/_app.tsx +++ b/packages/nextjs/pages/_app.tsx @@ -5,8 +5,12 @@ import "@rainbow-me/rainbowkit/styles.css"; import type { NextPage } from "next"; import NextNProgress from "nextjs-progressbar"; import { Toaster } from "react-hot-toast"; +// NEW +import { Provider } from "react-redux"; import { useDarkMode } from "usehooks-ts"; import { WagmiConfig } from "wagmi"; +// NEW +import { wrapper } from "~~/components/dash-wind/app/store"; import { BlockieAvatar } from "~~/components/scaffold-eth"; import { useNativeCurrencyPrice } from "~~/hooks/scaffold-eth"; import { useGlobalState } from "~~/services/store/store"; @@ -41,6 +45,8 @@ const ScaffoldEthApp = ({ Component, pageProps }: AppPropsWithLayout) => { const getLayout = Component.getLayout || (page => page); + const { store, props } = wrapper.useWrappedStore(pageProps); + return ( @@ -49,7 +55,10 @@ const ScaffoldEthApp = ({ Component, pageProps }: AppPropsWithLayout) => { avatar={BlockieAvatar} theme={isDarkTheme ? darkTheme() : lightTheme()} > -
{getLayout()}
+ +
{getLayout()}
+ {/*
{getLayout()}
*/} +
diff --git a/packages/nextjs/pages/dapp/404.tsx b/packages/nextjs/pages/dapp/404.tsx new file mode 100644 index 0000000..f5c04c9 --- /dev/null +++ b/packages/nextjs/pages/dapp/404.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import _404 from "~~/components/dash-wind/pages/protected/_404"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return <_404 />; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/blank.tsx b/packages/nextjs/pages/dapp/blank.tsx new file mode 100644 index 0000000..62abb07 --- /dev/null +++ b/packages/nextjs/pages/dapp/blank.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Blank from "~~/components/dash-wind/pages/protected/Blank"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/calendar.tsx b/packages/nextjs/pages/dapp/calendar.tsx new file mode 100644 index 0000000..63d7719 --- /dev/null +++ b/packages/nextjs/pages/dapp/calendar.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Calendar from "~~/components/dash-wind/pages/protected/Calendar"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/charts.tsx b/packages/nextjs/pages/dapp/charts.tsx new file mode 100644 index 0000000..0d4b1c0 --- /dev/null +++ b/packages/nextjs/pages/dapp/charts.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Charts from "~~/components/dash-wind/pages/protected/Charts"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/dashboard.tsx b/packages/nextjs/pages/dapp/dashboard.tsx new file mode 100644 index 0000000..f49432b --- /dev/null +++ b/packages/nextjs/pages/dapp/dashboard.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Dashboard from "~~/components/dash-wind/pages/protected/Dashboard"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/integration.tsx b/packages/nextjs/pages/dapp/integration.tsx new file mode 100644 index 0000000..71c3f0f --- /dev/null +++ b/packages/nextjs/pages/dapp/integration.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Integration from "~~/components/dash-wind/pages/protected/Integration"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/leads.tsx b/packages/nextjs/pages/dapp/leads.tsx new file mode 100644 index 0000000..8cfdebc --- /dev/null +++ b/packages/nextjs/pages/dapp/leads.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Leads from "~~/components/dash-wind/pages/protected/Leads"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/settings-billing.tsx b/packages/nextjs/pages/dapp/settings-billing.tsx new file mode 100644 index 0000000..6e0442d --- /dev/null +++ b/packages/nextjs/pages/dapp/settings-billing.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Bills from "~~/components/dash-wind/pages/protected/Bills"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/settings-profile.tsx b/packages/nextjs/pages/dapp/settings-profile.tsx new file mode 100644 index 0000000..860603c --- /dev/null +++ b/packages/nextjs/pages/dapp/settings-profile.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import ProfileSettings from "~~/components/dash-wind/pages/protected/ProfileSettings"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/settings-team.tsx b/packages/nextjs/pages/dapp/settings-team.tsx new file mode 100644 index 0000000..f08a3f0 --- /dev/null +++ b/packages/nextjs/pages/dapp/settings-team.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Team from "~~/components/dash-wind/pages/protected/Team"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/transactions.tsx b/packages/nextjs/pages/dapp/transactions.tsx new file mode 100644 index 0000000..8e93acf --- /dev/null +++ b/packages/nextjs/pages/dapp/transactions.tsx @@ -0,0 +1,19 @@ +import { ReactElement } from "react"; +import type { NextPageWithLayout } from "../_app"; +import Transactions from "~~/components/dash-wind/pages/protected/Transactions"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import DashLayout from "~~/components/layouts/DashLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappDashboard: NextPageWithLayout = () => { + return ; +}; + +DappDashboard.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappDashboard; diff --git a/packages/nextjs/pages/dapp/welcome.tsx b/packages/nextjs/pages/dapp/welcome.tsx new file mode 100644 index 0000000..f27d73a --- /dev/null +++ b/packages/nextjs/pages/dapp/welcome.tsx @@ -0,0 +1,20 @@ +import { ReactElement } from "react"; +import Welcome from "../../components/dash-wind/pages/protected/Welcome"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import CleanLayout from "../../components/layouts/CleanLayout"; +// import Link from "next/link"; +import type { NextPageWithLayout } from "../_app"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappWelcome: NextPageWithLayout = () => { + return ; +}; + +DappWelcome.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappWelcome; diff --git a/packages/nextjs/pages/forgot-password.tsx b/packages/nextjs/pages/forgot-password.tsx new file mode 100644 index 0000000..774fda7 --- /dev/null +++ b/packages/nextjs/pages/forgot-password.tsx @@ -0,0 +1,20 @@ +import { ReactElement } from "react"; +// import Link from "next/link"; +import type { NextPageWithLayout } from "./_app"; +import ForgotPassword from "~~/components/dash-wind/pages/ForgotPassword"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import CleanLayout from "~~/components/layouts/CleanLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappForgotPassword: NextPageWithLayout = () => { + return ; +}; + +DappForgotPassword.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappForgotPassword; diff --git a/packages/nextjs/pages/index.tsx b/packages/nextjs/pages/index.tsx index d2fd16f..dfc99f3 100644 --- a/packages/nextjs/pages/index.tsx +++ b/packages/nextjs/pages/index.tsx @@ -20,7 +20,7 @@ const LandingPage: NextPageWithLayout = () => { Web3Crew Constellation Project - + Launch Dapp diff --git a/packages/nextjs/pages/login.tsx b/packages/nextjs/pages/login.tsx new file mode 100644 index 0000000..f3e0941 --- /dev/null +++ b/packages/nextjs/pages/login.tsx @@ -0,0 +1,20 @@ +import { ReactElement } from "react"; +// import Link from "next/link"; +import type { NextPageWithLayout } from "./_app"; +import Login from "~~/components/dash-wind/pages/Login"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import CleanLayout from "~~/components/layouts/CleanLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappLogin: NextPageWithLayout = () => { + return ; +}; + +DappLogin.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappLogin; diff --git a/packages/nextjs/pages/dapp.tsx b/packages/nextjs/pages/orig_dapp.tsx similarity index 97% rename from packages/nextjs/pages/dapp.tsx rename to packages/nextjs/pages/orig_dapp.tsx index d4b49f1..7cd4313 100644 --- a/packages/nextjs/pages/dapp.tsx +++ b/packages/nextjs/pages/orig_dapp.tsx @@ -8,8 +8,7 @@ import LoginEmailOrWallet from "~~/components/web-3-crew/LoginEmailOrWallet"; import RegisterCompanyOrEmployee from "~~/components/web-3-crew/RegisterCompanyOrEmployee"; import RegisterCompanyForm from "~~/components/web-3-crew/forms/RegisterCompanyForm"; import RegisterEmployeeForm from "~~/components/web-3-crew/forms/RegisterEmployeeForm"; - -export type FormSteps = "start" | "login" | "signup" | "register-company" | "register-employee"; +import { FormSteps } from "~~/components/web-3-crew/types/FormSteps"; const LandingPage: NextPageWithLayout = () => { const [formState, setFormState] = useState("start"); diff --git a/packages/nextjs/pages/register.tsx b/packages/nextjs/pages/register.tsx new file mode 100644 index 0000000..4de6281 --- /dev/null +++ b/packages/nextjs/pages/register.tsx @@ -0,0 +1,20 @@ +import { ReactElement } from "react"; +// import Link from "next/link"; +import type { NextPageWithLayout } from "./_app"; +import Register from "~~/components/dash-wind/pages/Register"; +// import { MetaHeader } from "~~/components/MetaHeader"; +import CleanLayout from "~~/components/layouts/CleanLayout"; + +{ + /* Look into MetaHeader - should it be moved to _app.tsx ??? */ +} + +const DappRegister: NextPageWithLayout = () => { + return ; +}; + +DappRegister.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default DappRegister; diff --git a/packages/nextjs/tailwind.config.js b/packages/nextjs/tailwind.config.js index d63eb11..33cf01a 100644 --- a/packages/nextjs/tailwind.config.js +++ b/packages/nextjs/tailwind.config.js @@ -1,6 +1,11 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", "./utils/**/*.{js,ts,jsx,tsx}"], + content: [ + "./pages/**/*.{js,ts,jsx,tsx}", + "./components/**/*.{js,ts,jsx,tsx}", + "./utils/**/*.{js,ts,jsx,tsx}", + "./node_modules/react-tailwindcss-datepicker/dist/index.esm.js", + ], plugins: [require("daisyui")], darkTheme: "scaffoldEthDark", // DaisyUI theme colors diff --git a/packages/nextjs/tsconfig.json b/packages/nextjs/tsconfig.json index 708cc8e..c5f4636 100644 --- a/packages/nextjs/tsconfig.json +++ b/packages/nextjs/tsconfig.json @@ -16,8 +16,9 @@ "incremental": true, "paths": { "~~/*": ["./*"] - } + }, + "typeRoots": ["./node_modules/@types", "./components/dash-wind/types"] }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"], "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index 96163d7..d619705 100644 --- a/yarn.lock +++ b/yarn.lock @@ -162,6 +162,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.23.4 + resolution: "@babel/runtime@npm:7.23.4" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 8eb6a6b2367f7d60e7f7dd83f477cc2e2fdb169e5460694d7614ce5c730e83324bcf29251b70940068e757ad1ee56ff8073a372260d90cad55f18a825caf97cd + languageName: node + linkType: hard + "@babel/template@npm:^7.20.7": version: 7.20.7 resolution: "@babel/template@npm:7.20.7" @@ -915,6 +924,13 @@ __metadata: languageName: node linkType: hard +"@kurkle/color@npm:^0.3.0": + version: 0.3.2 + resolution: "@kurkle/color@npm:0.3.2" + checksum: 79e97b31f8f6efb28c69d373f94b0c7480226fe8ec95221f518ac998e156444a496727ce47de6d728eb5c3369288e794cba82cae34253deb0d472d3bfe080e49 + languageName: node + linkType: hard + "@ledgerhq/connect-kit-loader@npm:^1.1.0": version: 1.1.0 resolution: "@ledgerhq/connect-kit-loader@npm:1.1.0" @@ -1735,6 +1751,26 @@ __metadata: languageName: node linkType: hard +"@reduxjs/toolkit@npm:^1.9.7": + version: 1.9.7 + resolution: "@reduxjs/toolkit@npm:1.9.7" + dependencies: + immer: ^9.0.21 + redux: ^4.2.1 + redux-thunk: ^2.4.2 + reselect: ^4.1.8 + peerDependencies: + react: ^16.9.0 || ^17.0.0 || ^18 + react-redux: ^7.2.1 || ^8.0.2 + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true + checksum: ac25dec73a5d2df9fc7fbe98c14ccc73919e5ee1d6f251db0d2ec8f90273f92ef39c26716704bf56b5a40189f72d94b4526dc3a8c7ac3986f5daf44442bcc364 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^4.0.0": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" @@ -1906,6 +1942,7 @@ __metadata: "@ethersproject/providers": ^5.7.2 "@heroicons/react": ^2.0.11 "@rainbow-me/rainbowkit": 1.1.2 + "@reduxjs/toolkit": ^1.9.7 "@trivago/prettier-plugin-sort-imports": ^4.1.1 "@types/node": ^17.0.35 "@types/react": ^18.0.9 @@ -1914,22 +1951,32 @@ __metadata: "@uniswap/sdk-core": ^4.0.1 "@uniswap/v2-sdk": ^3.0.1 autoprefixer: ^10.4.12 + axios: ^1.6.2 blo: ^1.0.1 + chart.js: ^4.4.0 daisyui: ^3.5.1 + dayjs: 1.11.6 eslint: ^8.15.0 eslint-config-next: ^13.1.6 eslint-config-prettier: ^8.5.0 eslint-plugin-prettier: ^4.2.1 + moment: ^2.29.4 next: ^13.1.6 + next-redux-wrapper: ^8.1.0 nextjs-progressbar: ^0.0.16 postcss: ^8.4.16 prettier: ^2.8.4 qrcode.react: ^3.1.0 react: ^18.2.0 + react-chartjs-2: ^5.2.0 react-copy-to-clipboard: ^5.1.0 react-dom: ^18.2.0 react-hot-toast: ^2.4.0 + react-notifications: ^1.7.4 + react-redux: ^8.1.3 + react-tailwindcss-datepicker: ^1.6.6 tailwindcss: ^3.3.3 + theme-change: ^2.5.0 type-fest: ^4.6.0 typescript: ^5.1.6 use-debounce: ^8.0.4 @@ -2496,6 +2543,16 @@ __metadata: languageName: node linkType: hard +"@types/hoist-non-react-statics@npm:^3.3.1": + version: 3.3.5 + resolution: "@types/hoist-non-react-statics@npm:3.3.5" + dependencies: + "@types/react": "*" + hoist-non-react-statics: ^3.3.0 + checksum: b645b062a20cce6ab1245ada8274051d8e2e0b2ee5c6bd58215281d0ec6dae2f26631af4e2e7c8abe238cdcee73fcaededc429eef569e70908f82d0cc0ea31d7 + languageName: node + linkType: hard + "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.9": version: 7.0.11 resolution: "@types/json-schema@npm:7.0.11" @@ -2686,6 +2743,13 @@ __metadata: languageName: node linkType: hard +"@types/use-sync-external-store@npm:^0.0.3": + version: 0.0.3 + resolution: "@types/use-sync-external-store@npm:0.0.3" + checksum: 161ddb8eec5dbe7279ac971531217e9af6b99f7783213566d2b502e2e2378ea19cf5e5ea4595039d730aa79d3d35c6567d48599f69773a02ffcff1776ec2a44e + languageName: node + linkType: hard + "@types/ws@npm:^7.4.4": version: 7.4.7 resolution: "@types/ws@npm:7.4.7" @@ -3889,6 +3953,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:6.4.1": + version: 6.4.1 + resolution: "acorn@npm:6.4.1" + bin: + acorn: bin/acorn + checksum: 5ea4faa1fd30712b1d725da65e9612a93e566f40b0125df955c34669c33b81531e053a3c1501966e11217ca6026a0165f970e73c4eb8d3be7a957e4bef4ab67c + languageName: node + linkType: hard + "acorn@npm:^7.0.0": version: 7.4.1 resolution: "acorn@npm:7.4.1" @@ -4444,6 +4517,17 @@ __metadata: languageName: node linkType: hard +"axios@npm:^1.6.2": + version: 1.6.2 + resolution: "axios@npm:1.6.2" + dependencies: + follow-redirects: ^1.15.0 + form-data: ^4.0.0 + proxy-from-env: ^1.1.0 + checksum: 4a7429e2b784be0f2902ca2680964391eae7236faa3967715f30ea45464b98ae3f1c6f631303b13dfe721b17126b01f486c7644b9ef276bfc63112db9fd379f8 + languageName: node + linkType: hard + "axobject-query@npm:^2.2.0": version: 2.2.0 resolution: "axobject-query@npm:2.2.0" @@ -4986,6 +5070,15 @@ __metadata: languageName: node linkType: hard +"chart.js@npm:^4.4.0": + version: 4.4.0 + resolution: "chart.js@npm:4.4.0" + dependencies: + "@kurkle/color": ^0.3.0 + checksum: 5ee2d99b78608025525b5790af17178fdaa5adc3294e082deba2718029b0496109ba124f1b08dd1e4c8a04d6e842be7f384f2cfe9a11df8d1c6fe884acece52b + languageName: node + linkType: hard + "check-error@npm:^1.0.2": version: 1.0.2 resolution: "check-error@npm:1.0.2" @@ -5076,6 +5169,13 @@ __metadata: languageName: node linkType: hard +"classnames@npm:^2.1.1": + version: 2.3.2 + resolution: "classnames@npm:2.3.2" + checksum: 2c62199789618d95545c872787137262e741f9db13328e216b093eea91c85ef2bfb152c1f9e63027204e2559a006a92eb74147d46c800a9f96297ae1d9f96f4e + languageName: node + linkType: hard + "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -5539,6 +5639,13 @@ __metadata: languageName: node linkType: hard +"dayjs@npm:1.11.6": + version: 1.11.6 + resolution: "dayjs@npm:1.11.6" + checksum: 18bdfd927009b68eab08dca578e421d4a581cefcbe9337f54c5d9e0d941ffb6b221c4b2c1cab15cdd9d419940e768ac4c984531461a90bbe1c158b75fe160580 + languageName: node + linkType: hard + "death@npm:^1.1.0": version: 1.1.0 resolution: "death@npm:1.1.0" @@ -5896,6 +6003,16 @@ __metadata: languageName: node linkType: hard +"dom-helpers@npm:^5.0.1": + version: 5.2.1 + resolution: "dom-helpers@npm:5.2.1" + dependencies: + "@babel/runtime": ^7.8.7 + csstype: ^3.0.2 + checksum: 863ba9e086f7093df3376b43e74ce4422571d404fc9828bf2c56140963d5edf0e56160f9b2f3bb61b282c07f8fc8134f023c98fd684bddcb12daf7b0f14d951c + languageName: node + linkType: hard + "dotenv@npm:^16.0.3": version: 16.0.3 resolution: "dotenv@npm:16.0.3" @@ -8204,6 +8321,15 @@ __metadata: languageName: node linkType: hard +"hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2": + version: 3.3.2 + resolution: "hoist-non-react-statics@npm:3.3.2" + dependencies: + react-is: ^16.7.0 + checksum: b1538270429b13901ee586aa44f4cc3ecd8831c061d06cb8322e50ea17b3f5ce4d0e2e66394761e6c8e152cd8c34fb3b4b690116c6ce2bd45b18c746516cb9e8 + languageName: node + linkType: hard + "http-basic@npm:^8.1.1": version: 8.1.3 resolution: "http-basic@npm:8.1.3" @@ -8352,6 +8478,13 @@ __metadata: languageName: node linkType: hard +"immer@npm:^9.0.21": + version: 9.0.21 + resolution: "immer@npm:9.0.21" + checksum: 70e3c274165995352f6936695f0ef4723c52c92c92dd0e9afdfe008175af39fa28e76aafb3a2ca9d57d1fb8f796efc4dd1e1cc36f18d33fa5b74f3dfb0375432 + languageName: node + linkType: hard + "immutable@npm:^4.0.0-rc.12": version: 4.1.0 resolution: "immutable@npm:4.1.0" @@ -9886,6 +10019,13 @@ __metadata: languageName: node linkType: hard +"moment@npm:^2.29.4": + version: 2.29.4 + resolution: "moment@npm:2.29.4" + checksum: 0ec3f9c2bcba38dc2451b1daed5daded747f17610b92427bebe1d08d48d8b7bdd8d9197500b072d14e326dd0ccf3e326b9e3d07c5895d3d49e39b6803b76e80e + languageName: node + linkType: hard + "motion@npm:10.16.2": version: 10.16.2 resolution: "motion@npm:10.16.2" @@ -10028,6 +10168,17 @@ __metadata: languageName: node linkType: hard +"next-redux-wrapper@npm:^8.1.0": + version: 8.1.0 + resolution: "next-redux-wrapper@npm:8.1.0" + peerDependencies: + next: ">=9" + react: "*" + react-redux: "*" + checksum: 74fa21355094cf678a7aa24e3baa98328746e42fe41d3e2a779d7d06d025bf980b71f313805300d854c320904ee7e72a3772842e2b023df70d2571dfa998c2e7 + languageName: node + linkType: hard + "next@npm:^13.1.6": version: 13.1.6 resolution: "next@npm:13.1.6" @@ -11116,7 +11267,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.8.1": +"prop-types@npm:^15.5.10, prop-types@npm:^15.6.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -11308,6 +11459,16 @@ __metadata: languageName: node linkType: hard +"react-chartjs-2@npm:^5.2.0": + version: 5.2.0 + resolution: "react-chartjs-2@npm:5.2.0" + peerDependencies: + chart.js: ^4.1.1 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: ace702185be1450e5888a8bcd8b5fc1995067e3b11d236764a67f5567a3d7c32ff16923b8d48d3d39bda6e45135da6c044c9b43fbe8e1978f95aca9d2c0ce348 + languageName: node + linkType: hard + "react-copy-to-clipboard@npm:^5.1.0": version: 5.1.0 resolution: "react-copy-to-clipboard@npm:5.1.0" @@ -11344,13 +11505,64 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.13.1": +"react-is@npm:^16.13.1, react-is@npm:^16.7.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f languageName: node linkType: hard +"react-is@npm:^18.0.0": + version: 18.2.0 + resolution: "react-is@npm:18.2.0" + checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e + languageName: node + linkType: hard + +"react-notifications@npm:^1.7.4": + version: 1.7.4 + resolution: "react-notifications@npm:1.7.4" + dependencies: + acorn: 6.4.1 + classnames: ^2.1.1 + prop-types: ^15.5.10 + react-transition-group: ^4.4.1 + checksum: 01e404a3477e7cc749f9561c97c69359f20d935f673a4e4abce42e29c20cac7b694320eb95525d79bbbc0eaaa88f153068f34e24f8044ec248781f89462869b5 + languageName: node + linkType: hard + +"react-redux@npm:^8.1.3": + version: 8.1.3 + resolution: "react-redux@npm:8.1.3" + dependencies: + "@babel/runtime": ^7.12.1 + "@types/hoist-non-react-statics": ^3.3.1 + "@types/use-sync-external-store": ^0.0.3 + hoist-non-react-statics: ^3.3.2 + react-is: ^18.0.0 + use-sync-external-store: ^1.0.0 + peerDependencies: + "@types/react": ^16.8 || ^17.0 || ^18.0 + "@types/react-dom": ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + react-native: ">=0.59" + redux: ^4 || ^5.0.0-beta.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + react-dom: + optional: true + react-native: + optional: true + redux: + optional: true + checksum: 192ea6f6053148ec80a4148ec607bc259403b937e515f616a1104ca5ab357e97e98b8245ed505a17afee67a72341d4a559eaca9607968b4a422aa9b44ba7eb89 + languageName: node + linkType: hard + "react-remove-scroll-bar@npm:^2.3.3": version: 2.3.3 resolution: "react-remove-scroll-bar@npm:2.3.3" @@ -11403,6 +11615,31 @@ __metadata: languageName: node linkType: hard +"react-tailwindcss-datepicker@npm:^1.6.6": + version: 1.6.6 + resolution: "react-tailwindcss-datepicker@npm:1.6.6" + peerDependencies: + dayjs: ^1.11.6 + react: ^17.0.2 || ^18.2.0 + checksum: d995a775aa773fadf36dda67f6b678e5a5682df2df339289ae0a079f77e7a629c92092826e2570ae45245f0f5e19fc4f909e59ed316e837727e46fe3fd837360 + languageName: node + linkType: hard + +"react-transition-group@npm:^4.4.1": + version: 4.4.5 + resolution: "react-transition-group@npm:4.4.5" + dependencies: + "@babel/runtime": ^7.5.5 + dom-helpers: ^5.0.1 + loose-envify: ^1.4.0 + prop-types: ^15.6.2 + peerDependencies: + react: ">=16.6.0" + react-dom: ">=16.6.0" + checksum: 75602840106aa9c6545149d6d7ae1502fb7b7abadcce70a6954c4b64a438ff1cd16fc77a0a1e5197cdd72da398f39eb929ea06f9005c45b132ed34e056ebdeb1 + languageName: node + linkType: hard + "react@npm:^18.2.0": version: 18.2.0 resolution: "react@npm:18.2.0" @@ -11535,6 +11772,24 @@ __metadata: languageName: node linkType: hard +"redux-thunk@npm:^2.4.2": + version: 2.4.2 + resolution: "redux-thunk@npm:2.4.2" + peerDependencies: + redux: ^4 + checksum: c7f757f6c383b8ec26152c113e20087818d18ed3edf438aaad43539e9a6b77b427ade755c9595c4a163b6ad3063adf3497e5fe6a36c68884eb1f1cfb6f049a5c + languageName: node + linkType: hard + +"redux@npm:^4.2.1": + version: 4.2.1 + resolution: "redux@npm:4.2.1" + dependencies: + "@babel/runtime": ^7.9.2 + checksum: f63b9060c3a1d930ae775252bb6e579b42415aee7a23c4114e21a0b4ba7ec12f0ec76936c00f546893f06e139819f0e2855e0d55ebfce34ca9c026241a6950dd + languageName: node + linkType: hard + "regenerator-runtime@npm:^0.13.4": version: 0.13.9 resolution: "regenerator-runtime@npm:0.13.9" @@ -11542,6 +11797,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.14.0": + version: 0.14.0 + resolution: "regenerator-runtime@npm:0.14.0" + checksum: 1c977ad82a82a4412e4f639d65d22be376d3ebdd30da2c003eeafdaaacd03fc00c2320f18120007ee700900979284fc78a9f00da7fb593f6e6eeebc673fba9a3 + languageName: node + linkType: hard + "regexp.prototype.flags@npm:^1.4.1, regexp.prototype.flags@npm:^1.4.3": version: 1.4.3 resolution: "regexp.prototype.flags@npm:1.4.3" @@ -11651,6 +11913,13 @@ __metadata: languageName: node linkType: hard +"reselect@npm:^4.1.8": + version: 4.1.8 + resolution: "reselect@npm:4.1.8" + checksum: a4ac87cedab198769a29be92bc221c32da76cfdad6911eda67b4d3e7136dca86208c3b210e31632eae31ebd2cded18596f0dd230d3ccc9e978df22f233b5583e + languageName: node + linkType: hard + "resolve-from@npm:^3.0.0": version: 3.0.0 resolution: "resolve-from@npm:3.0.0" @@ -12993,6 +13262,13 @@ __metadata: languageName: node linkType: hard +"theme-change@npm:^2.5.0": + version: 2.5.0 + resolution: "theme-change@npm:2.5.0" + checksum: a57e50a8f7cb0390c752c9f3b44aa38bdb37ad72cfed1770a9cad3f718b620eec7e2a18abf6706730eb76a55f67ec813c17192dbe4943b03371c1e13e589ec15 + languageName: node + linkType: hard + "then-request@npm:^6.0.0": version: 6.0.2 resolution: "then-request@npm:6.0.2" @@ -13615,7 +13891,7 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:1.2.0, use-sync-external-store@npm:^1.2.0": +"use-sync-external-store@npm:1.2.0, use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.2.0": version: 1.2.0 resolution: "use-sync-external-store@npm:1.2.0" peerDependencies: