diff --git a/client/next.config.js b/client/next.config.js index b9c6440d..fbdea080 100644 --- a/client/next.config.js +++ b/client/next.config.js @@ -13,6 +13,15 @@ const nextConfig = { ], }, output: 'standalone', + async redirects() { + return [ + { + source: '/auth', + destination: '/auth/details', + permanent: true, + }, + ]; + }, }; module.exports = withPlugins( diff --git a/client/src/constants/nav.ts b/client/src/constants/nav.ts index 27176617..57b6d397 100644 --- a/client/src/constants/nav.ts +++ b/client/src/constants/nav.ts @@ -1,4 +1,15 @@ -export const NAV = [ +type NavItem = { + label: string; + href: string; + filled?: boolean; + target?: string; + rel?: string; + className?: string; + auth?: boolean; + footer?: boolean; +}; + +export const NAV: NavItem[] = [ { label: 'Home', href: '/', @@ -37,11 +48,26 @@ export const NAV = [ { label: 'Log In', href: '/auth/signin', - className: 'border border-grey-0 rounded-lg !bg-white', + className: 'border border-grey-0 rounded-lg bg-white', auth: true, }, ]; +export const NAV_AUTH: NavItem[] = [ + { + label: 'My details', + href: '/auth/details', + }, + { + label: 'My projects', + href: '/auth/projects', + }, + { + label: 'My investments', + href: '/auth/investments', + }, +]; + export const POLICIES = [ { label: 'Privacy policy', diff --git a/client/src/containers/my-projects/constants.ts b/client/src/containers/auth/projects/constants.ts similarity index 100% rename from client/src/containers/my-projects/constants.ts rename to client/src/containers/auth/projects/constants.ts diff --git a/client/src/containers/my-projects/form/form.test.tsx b/client/src/containers/auth/projects/form/form.test.tsx similarity index 100% rename from client/src/containers/my-projects/form/form.test.tsx rename to client/src/containers/auth/projects/form/form.test.tsx diff --git a/client/src/containers/my-projects/form/index.tsx b/client/src/containers/auth/projects/form/index.tsx similarity index 100% rename from client/src/containers/my-projects/form/index.tsx rename to client/src/containers/auth/projects/form/index.tsx diff --git a/client/src/containers/my-projects/form/label.tsx b/client/src/containers/auth/projects/form/label.tsx similarity index 100% rename from client/src/containers/my-projects/form/label.tsx rename to client/src/containers/auth/projects/form/label.tsx diff --git a/client/src/containers/my-projects/form/legend.tsx b/client/src/containers/auth/projects/form/legend.tsx similarity index 100% rename from client/src/containers/my-projects/form/legend.tsx rename to client/src/containers/auth/projects/form/legend.tsx diff --git a/client/src/containers/my-projects/form/steps/contact-details/index.tsx b/client/src/containers/auth/projects/form/steps/contact-details/index.tsx similarity index 100% rename from client/src/containers/my-projects/form/steps/contact-details/index.tsx rename to client/src/containers/auth/projects/form/steps/contact-details/index.tsx diff --git a/client/src/containers/my-projects/form/steps/contact-details/primary-office-country.tsx b/client/src/containers/auth/projects/form/steps/contact-details/primary-office-country.tsx similarity index 93% rename from client/src/containers/my-projects/form/steps/contact-details/primary-office-country.tsx rename to client/src/containers/auth/projects/form/steps/contact-details/primary-office-country.tsx index 2be581ee..e818e4fc 100644 --- a/client/src/containers/my-projects/form/steps/contact-details/primary-office-country.tsx +++ b/client/src/containers/auth/projects/form/steps/contact-details/primary-office-country.tsx @@ -6,7 +6,7 @@ import { Field as FieldRFF } from 'react-final-form'; import { useSubGeographics } from 'hooks/geographics'; -import { ProjectSchema } from 'containers/my-projects/form/validations'; +import { ProjectSchema } from 'containers/auth/projects/form/validations'; import { Select } from 'components/forms'; diff --git a/client/src/containers/my-projects/form/steps/contact-details/primary-office-state.tsx b/client/src/containers/auth/projects/form/steps/contact-details/primary-office-state.tsx similarity index 95% rename from client/src/containers/my-projects/form/steps/contact-details/primary-office-state.tsx rename to client/src/containers/auth/projects/form/steps/contact-details/primary-office-state.tsx index c937935f..3a8e2087 100644 --- a/client/src/containers/my-projects/form/steps/contact-details/primary-office-state.tsx +++ b/client/src/containers/auth/projects/form/steps/contact-details/primary-office-state.tsx @@ -6,7 +6,7 @@ import { Field as FieldRFF, useForm, useFormState } from 'react-final-form'; import { useSubGeographics } from 'hooks/geographics'; -import { ProjectSchema } from 'containers/my-projects/form/validations'; +import { ProjectSchema } from 'containers/auth/projects/form/validations'; import { Select } from 'components/forms'; diff --git a/client/src/containers/my-projects/form/steps/project-details/demographics.tsx b/client/src/containers/auth/projects/form/steps/project-details/demographics.tsx similarity index 93% rename from client/src/containers/my-projects/form/steps/project-details/demographics.tsx rename to client/src/containers/auth/projects/form/steps/project-details/demographics.tsx index 0973c02e..14d817d7 100644 --- a/client/src/containers/my-projects/form/steps/project-details/demographics.tsx +++ b/client/src/containers/auth/projects/form/steps/project-details/demographics.tsx @@ -6,7 +6,7 @@ import { Field as FieldRFF } from 'react-final-form'; import { useDemographics } from 'hooks/demographics'; -import { ProjectSchema } from 'containers/my-projects/form/validations'; +import { ProjectSchema } from 'containers/auth/projects/form/validations'; import { MultiSelect, Select } from 'components/forms'; diff --git a/client/src/containers/my-projects/form/steps/project-details/index.tsx b/client/src/containers/auth/projects/form/steps/project-details/index.tsx similarity index 100% rename from client/src/containers/my-projects/form/steps/project-details/index.tsx rename to client/src/containers/auth/projects/form/steps/project-details/index.tsx diff --git a/client/src/containers/my-projects/form/steps/project-details/legal-status.tsx b/client/src/containers/auth/projects/form/steps/project-details/legal-status.tsx similarity index 93% rename from client/src/containers/my-projects/form/steps/project-details/legal-status.tsx rename to client/src/containers/auth/projects/form/steps/project-details/legal-status.tsx index 84e41e79..131bccfc 100644 --- a/client/src/containers/my-projects/form/steps/project-details/legal-status.tsx +++ b/client/src/containers/auth/projects/form/steps/project-details/legal-status.tsx @@ -6,7 +6,7 @@ import { Field as FieldRFF } from 'react-final-form'; import { useProjectLegalStatuses } from 'hooks/project-legal-statuses'; -import { ProjectSchema } from 'containers/my-projects/form/validations'; +import { ProjectSchema } from 'containers/auth/projects/form/validations'; import { Select } from 'components/forms'; diff --git a/client/src/containers/my-projects/form/validations.ts b/client/src/containers/auth/projects/form/validations.ts similarity index 100% rename from client/src/containers/my-projects/form/validations.ts rename to client/src/containers/auth/projects/form/validations.ts diff --git a/client/src/containers/my-projects/form/wrapper.tsx b/client/src/containers/auth/projects/form/wrapper.tsx similarity index 100% rename from client/src/containers/my-projects/form/wrapper.tsx rename to client/src/containers/auth/projects/form/wrapper.tsx diff --git a/client/src/containers/my-projects/new/header.tsx b/client/src/containers/auth/projects/new/header.tsx similarity index 100% rename from client/src/containers/my-projects/new/header.tsx rename to client/src/containers/auth/projects/new/header.tsx diff --git a/client/src/containers/my-projects/new/index.tsx b/client/src/containers/auth/projects/new/index.tsx similarity index 52% rename from client/src/containers/my-projects/new/index.tsx rename to client/src/containers/auth/projects/new/index.tsx index 1630e024..bb0c367b 100644 --- a/client/src/containers/my-projects/new/index.tsx +++ b/client/src/containers/auth/projects/new/index.tsx @@ -39,7 +39,7 @@ export default function NewProject() { }); }, onSuccess: () => { - push('/my-projects/new?step=investments'); + push('/projects/new?step=investments'); }, }); @@ -53,48 +53,46 @@ export default function NewProject() { }, [mutation]); return ( -
- - { - const formData = new FormData(); - - for (const key in data) { - if (data.hasOwnProperty(key)) { - const value = data[key]; - - if (Array.isArray(value)) { - value.forEach((v) => { - formData.append(`${key}[]`, v); - }); - } else { - formData.append(key, value); - } + + { + const formData = new FormData(); + + for (const key in data) { + if (data.hasOwnProperty(key)) { + const value = data[key]; + + if (Array.isArray(value)) { + value.forEach((v) => { + formData.append(`${key}[]`, v); + }); + } else { + formData.append(key, value); } } - - formData.append('contact_first_name', me?.name.split(' ')[0]); - formData.append('contact_last_name', me?.name.split(' ')[1]); - - mutation.mutate(formData); - }} - render={({ handleSubmit }) => { - return ( -
- -
-
- -
-
-
-
+ } + + formData.append('contact_first_name', me?.name.split(' ')[0]); + formData.append('contact_last_name', me?.name.split(' ')[1]); + + mutation.mutate(formData); + }} + render={({ handleSubmit }) => { + return ( +
+ +
+
+ +
+
+
- ); - }} - /> - -
+
+ ); + }} + /> + ); } diff --git a/client/src/containers/my-projects/new/investments.tsx b/client/src/containers/auth/projects/new/investments.tsx similarity index 92% rename from client/src/containers/my-projects/new/investments.tsx rename to client/src/containers/auth/projects/new/investments.tsx index 6269b30f..79606214 100644 --- a/client/src/containers/my-projects/new/investments.tsx +++ b/client/src/containers/auth/projects/new/investments.tsx @@ -25,7 +25,7 @@ export default function InvestmentsStep() { sit sagittis.

Report Investment diff --git a/client/src/containers/my-projects/sidebar.test.tsx b/client/src/containers/auth/projects/sidebar.test.tsx similarity index 100% rename from client/src/containers/my-projects/sidebar.test.tsx rename to client/src/containers/auth/projects/sidebar.test.tsx diff --git a/client/src/containers/my-projects/sidebar.tsx b/client/src/containers/auth/projects/sidebar.tsx similarity index 100% rename from client/src/containers/my-projects/sidebar.tsx rename to client/src/containers/auth/projects/sidebar.tsx diff --git a/client/src/containers/header/component.tsx b/client/src/containers/header/component.tsx index cf2b6970..96953c0c 100644 --- a/client/src/containers/header/component.tsx +++ b/client/src/containers/header/component.tsx @@ -1,42 +1,43 @@ import React, { useCallback, useMemo } from 'react'; -import cx from 'classnames'; - import Image from 'next/image'; import Link from 'next/link'; -import { useRouter } from 'next/router'; +import { usePathname } from 'next/navigation'; + +import { cn } from 'lib/utils'; import { useSession } from 'next-auth/react'; -import { NAV } from 'constants/nav'; +import { NAV, NAV_AUTH } from 'constants/nav'; import Wrapper from 'containers/wrapper'; import { Button } from 'components/button/component'; import CircleUserIcon from 'components/icons/circle-user'; +import { isPrivatePath } from 'middleware'; import LOGO_SVG from 'svgs/logo.svg'; const Header = () => { - const { pathname } = useRouter(); + const pathname = usePathname(); const { data: session } = useSession(); - const isAuthPath = useMemo(() => pathname.includes('/auth'), [pathname]); + const isAuthPath = isPrivatePath(pathname); + const NAV_ITEMS = useMemo(() => { + if (isAuthPath) return NAV_AUTH; return NAV.filter((n) => !n.footer && !(session && n.auth)); - }, [session]); + }, [session, isAuthPath]); const isActiveNavItem = useCallback( (href: string) => { - if (isAuthPath) return false; - return pathname.includes(href) && pathname !== '/'; }, - [pathname, isAuthPath] + [pathname] ); return (
{ href={href} target={target} rel={rel} - className={cx({ + className={cn({ 'text-base font-semibold py-2 px-7': true, 'hover:rounded-lg hover:bg-grey-60/75': pathname !== href, 'rounded-lg bg-green-0': isActiveNavItem(href), @@ -81,13 +82,13 @@ const Header = () => { {!target && ( { ); })} {session && ( - )} diff --git a/client/src/hoc/auth.ts b/client/src/hoc/auth.ts index 3ae9a0c3..80c610c8 100644 --- a/client/src/hoc/auth.ts +++ b/client/src/hoc/auth.ts @@ -21,7 +21,7 @@ export function withAuth(gssp?: GetServerSideProps) { // Public route (auth pages) with session -> redirect to projects return { redirect: { - destination: '/projects', + destination: '/auth/details', permanent: false, }, }; diff --git a/client/src/layouts/application/component.tsx b/client/src/layouts/application/component.tsx index 508e027f..5429e4a9 100644 --- a/client/src/layouts/application/component.tsx +++ b/client/src/layouts/application/component.tsx @@ -1,35 +1,33 @@ -import cx from 'classnames'; +import { PropsWithChildren } from 'react'; -import { useRouter } from 'next/router'; +import { usePathname } from 'next/navigation'; + +import { cn } from 'lib/utils'; import Footer from 'containers/footer'; import Header from 'containers/header'; -type ApplicationLayoutProps = { - children: React.ReactNode; -}; - -const ApplicationLayout: React.FC = (props: ApplicationLayoutProps) => { - const { children } = props; - const { pathname } = useRouter(); +export default function ApplicationLayout({ children }: PropsWithChildren) { + const pathname = usePathname(); + const isAuthRoute = pathname.includes('/auth'); return (
- -
- {/* Content */} +
{children}
-
); -}; - -export default ApplicationLayout; +} diff --git a/client/src/middleware.ts b/client/src/middleware.ts index 617a7f0a..3b14ffe5 100644 --- a/client/src/middleware.ts +++ b/client/src/middleware.ts @@ -1,5 +1,21 @@ -export { default } from 'next-auth/middleware'; +import { NextResponse } from 'next/server'; -export const config = { - matcher: ['/my-details/:path*', '/my-projects/:path*', '/my-investments/:path*'], +import { NextRequestWithAuth, withAuth } from 'next-auth/middleware'; + +const PRIVATE_PAGES = /^(\/auth(?!\/signin|\/signup|\/forgot-password))/; + +export const isPrivatePath = (pathname: string) => { + return PRIVATE_PAGES.test(pathname); }; + +export default function middleware(req: NextRequestWithAuth) { + if (isPrivatePath(req.nextUrl.pathname)) { + return withAuth(req, { + pages: { + signIn: '/auth/signin', + }, + }); + } + + return NextResponse.next(); +} diff --git a/client/src/pages/404.tsx b/client/src/pages/404.tsx index 09e952b4..a6f64ddf 100644 --- a/client/src/pages/404.tsx +++ b/client/src/pages/404.tsx @@ -11,7 +11,7 @@ const Page404: React.FC = () => {

Page not found

-

It looks like the link is broken or the pages has been removed.

+

It looks like the link is broken or the page has been removed.