diff --git a/src/assets/svg/facebook.svg b/src/assets/svg/facebook.svg new file mode 100644 index 0000000..53f04b9 --- /dev/null +++ b/src/assets/svg/facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svg/instagram.svg b/src/assets/svg/instagram.svg new file mode 100644 index 0000000..27fca3d --- /dev/null +++ b/src/assets/svg/instagram.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svg/rmProps.sh b/src/assets/svg/rmProps.sh new file mode 100644 index 0000000..2162617 --- /dev/null +++ b/src/assets/svg/rmProps.sh @@ -0,0 +1,6 @@ +#!/bin/bash +ls *.svg | while read filename; do +sed -i '1 s/width=\"..\" height=\"..\" //' $filename; +sed -i 's/fill=\"#262626\"/stroke="none"/' $filename; +sed -i 's/stroke=\"#262626\"/fill="none"/' $filename +done \ No newline at end of file diff --git a/src/components/ContextMenu.tsx b/src/components/ContextMenu.tsx new file mode 100644 index 0000000..0073083 --- /dev/null +++ b/src/components/ContextMenu.tsx @@ -0,0 +1,115 @@ +/* -------------------------------------------------------------------------- */ +/* Imports */ +/* -------------------------------------------------------------------------- */ +import React, { Fragment } from "react"; +import { Menu, Transition } from "@headlessui/react"; +import { PropsPartion } from "./ContextMenuItem"; +import classNames from "classnames"; +import { ReactComponent as SelectIcon } from "assets/svg/select-arrow.svg"; +type ChildType = React.ReactElement; +type ChildrenType = ChildType[] | ChildType; + +/* -------------------------------------------------------------------------- */ +/* Component props */ +/* -------------------------------------------------------------------------- */ + +type MenuProps = { + emphasis?: "high" | "low"; + disabled?: boolean; + className?: string | undefined; + button: React.ReactNode; + children: ChildrenType; +}; +/* -------------------------------------------------------------------------- */ +/* Styles */ +/* -------------------------------------------------------------------------- */ + +const MenuButtonStyle = ` +inline-flex +justify-center w-full +cursor-default +rounded +border border-gray-100 +outline-8 +py-2 +px-2 +text-base`; + +const MenuItemStyle = ` +absolute +left-0 +mt-2 w-60 +origin-top-left +rounded +shadow-lg +focus:outline-none +py-2 px-4 sm:text-sm`; + +/* -------------------------------------------------------------------------- */ +/* Component implementation */ +/* -------------------------------------------------------------------------- */ +/** + * Use width ContextMenuAction.tsx , for example: + * + * alert('click')} + * > + * ... + * + */ +export default function ContextMenu({ + button, + children, + className, + emphasis = "low", +}: MenuProps) { + return ( + + {({ open }) => ( + <> + + {button} + + + + + {children} + + + + )} + + ); +} diff --git a/src/components/ContextMenuAction.tsx b/src/components/ContextMenuAction.tsx new file mode 100644 index 0000000..8d1e653 --- /dev/null +++ b/src/components/ContextMenuAction.tsx @@ -0,0 +1,32 @@ +import classNames from "classnames"; +import React from "react"; + +type Props = { + action: Function; + caption: string; + disabled?: boolean; + icon?: React.ReactNode; + className?: string | undefined; +}; + +export default function ContextMenuAction({ + action, + caption, + disabled, + icon, + className, +}: Props) { + return ( + action(e)} + className={classNames([ + "group flex px-2 rounded items-center text-base hover:bg-gray-100", + className, + ])} + > + {icon &&
{icon}
} + {caption} +
+ ); +} diff --git a/src/components/parts/Footer.tsx b/src/components/parts/Footer.tsx new file mode 100644 index 0000000..dcc3331 --- /dev/null +++ b/src/components/parts/Footer.tsx @@ -0,0 +1,115 @@ +import React, { useMemo } from "react"; +/* -------------------------------------------------------------------------- */ +/* Import Components */ +/* -------------------------------------------------------------------------- */ +import Typography from "components/typography/Typography"; +import { SVGFacebook, SVGInstagram, SVGCircle } from "components/icons"; +import { RouterLink } from "components/typography/RouterLink"; +import Link from "components/typography/Link"; + +/* -------------------------------------------------------------------------- */ +/* Define consts */ +/* -------------------------------------------------------------------------- */ + +const mainLinks = [ + { label: "account settings", url: "/account/settings", enabled: true }, + { label: "about freeland", url: "/about", enabled: true }, + { label: "help", url: "/help", enabled: true }, + { label: "contact us", url: "/contact-us", enabled: true }, +]; + +const secondaryLinks = [ + { index: 1, label: "Terms of Use", url: "/terms-of-use", enabled: true }, + { index: 2, label: "Privacy Policy", url: "/privacy-policy", enabled: true }, + { index: 3, label: "Cookies Policy", url: "/cookies-policy", enabled: true }, +]; + +/* -------------------------------------------------------------------------- */ +/* Difine parts of footer */ +/* -------------------------------------------------------------------------- */ + +/* -------------------- Icons with social networks icons -------------------- */ +const circleDivider = ( + +); + +/* -------------------------------------------------------------------------- */ +/* Define component footer */ +/* -------------------------------------------------------------------------- */ + +export function Footer() { + /* -------------------------- Part with main links -------------------------- */ + const mainLinksPart = useMemo( + () => + mainLinks.map((link) => ( + + + {link.label.toUpperCase()} + + + )), + mainLinks + ); + /* ------------------------ Part with secondary links ----------------------- */ + const secondaryLinksPart = useMemo( + () => + secondaryLinks.map((link) => ( +
+ {link.index != 1 && circleDivider} + + {link.label} + +
+ )), + secondaryLinks + ); + + /* -------------------------------------------------------------------------- */ + /* Implement footer component */ + /* -------------------------------------------------------------------------- */ + return ( +
+
+
+ + + Freeland + + +
+
+ {mainLinksPart} +
+
+ + + + + {" "} + + +
+
+
+
+ + @ Copyright 2022 Freeland - All rights reserved + +
{circleDivider}
+
{secondaryLinksPart}
+
+
+ Supported by + + Comfortel + +
+
+
+ ); +} diff --git a/src/components/typography/RouterLink.tsx b/src/components/typography/RouterLink.tsx new file mode 100644 index 0000000..4b32e77 --- /dev/null +++ b/src/components/typography/RouterLink.tsx @@ -0,0 +1,18 @@ +import classNames from "classnames"; +import { NavLink, NavLinkProps, To } from "react-router-dom"; + +type Props = { + enabled?: boolean; + children?: React.ReactNode; +} & NavLinkProps; + +export function RouterLink({ children, enabled = true, className, to }: Props) { + return ( + + {children} + + ); +} diff --git a/src/index.tsx b/src/index.tsx index 67c9221..c390a65 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,16 +1,39 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from "react"; +import ReactDOM from "react-dom/client"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; import "./localization/i18n"; +import About from "pages/Information/About"; +import Help from "pages/Information/Help"; +import ContactUs from "pages/Information/ContactUs"; +import TermsOfUse from "pages/Information/TermsOfUse"; +import PrivacyPolicy from "pages/Information/PrivacyPolicy"; +import CookiesPolicy from "pages/Information/CookiesPolicy"; +import AccountSettings from "pages/Information/AccountSettings"; -ReactDOM.render( +const rootElement = document.getElementById("root"); +if (!rootElement) throw new Error("Failed to find the root element"); +const root = ReactDOM.createRoot(rootElement); +root.render( - - , - document.getElementById('root') + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + } /> + + + + ); // If you want to start measuring performance in your app, pass a function diff --git a/src/pages/Information/About.tsx b/src/pages/Information/About.tsx new file mode 100644 index 0000000..ce57d7e --- /dev/null +++ b/src/pages/Information/About.tsx @@ -0,0 +1,15 @@ +import BaseLayout from "components/BaseLayout"; +import { Footer } from "components/parts/Footer"; +import Header from "components/parts/Header"; +import Typography from "components/typography/Typography"; +import React from "react"; + +type Props = {}; + +export default function About({}: Props) { + return ( + + About page + + ); +} diff --git a/src/pages/Information/AccountSettings.tsx b/src/pages/Information/AccountSettings.tsx new file mode 100644 index 0000000..983334f --- /dev/null +++ b/src/pages/Information/AccountSettings.tsx @@ -0,0 +1,15 @@ +import BaseLayout from "components/BaseLayout"; +import { Footer } from "components/parts/Footer"; +import Header from "components/parts/Header"; +import Typography from "components/typography/Typography"; +import React from "react"; + +type Props = {}; + +export default function AccountSettings({}: Props) { + return ( + + Accont Setting page + + ); +} diff --git a/src/pages/Information/ContactUs.tsx b/src/pages/Information/ContactUs.tsx new file mode 100644 index 0000000..271cfa2 --- /dev/null +++ b/src/pages/Information/ContactUs.tsx @@ -0,0 +1,15 @@ +import BaseLayout from "components/BaseLayout"; +import { Footer } from "components/parts/Footer"; +import Header from "components/parts/Header"; +import Typography from "components/typography/Typography"; +import React from "react"; + +type Props = {}; + +export default function ContactUs({}: Props) { + return ( + + Contact us page + + ); +} diff --git a/src/pages/Information/CookiesPolicy.tsx b/src/pages/Information/CookiesPolicy.tsx new file mode 100644 index 0000000..42c0980 --- /dev/null +++ b/src/pages/Information/CookiesPolicy.tsx @@ -0,0 +1,15 @@ +import BaseLayout from "components/BaseLayout"; +import { Footer } from "components/parts/Footer"; +import Header from "components/parts/Header"; +import Typography from "components/typography/Typography"; +import React from "react"; + +type Props = {}; + +export default function CookiesPolicy({}: Props) { + return ( + + Privacy Cookies page + + ); +} diff --git a/src/pages/Information/Help.tsx b/src/pages/Information/Help.tsx new file mode 100644 index 0000000..996b488 --- /dev/null +++ b/src/pages/Information/Help.tsx @@ -0,0 +1,15 @@ +import BaseLayout from "components/BaseLayout"; +import { Footer } from "components/parts/Footer"; +import Header from "components/parts/Header"; +import Typography from "components/typography/Typography"; +import React from "react"; + +type Props = {}; + +export default function Help({}: Props) { + return ( + + Help page + + ); +} diff --git a/src/pages/Information/PrivacyPolicy.tsx b/src/pages/Information/PrivacyPolicy.tsx new file mode 100644 index 0000000..fa35eff --- /dev/null +++ b/src/pages/Information/PrivacyPolicy.tsx @@ -0,0 +1,15 @@ +import BaseLayout from "components/BaseLayout"; +import { Footer } from "components/parts/Footer"; +import Header from "components/parts/Header"; +import Typography from "components/typography/Typography"; +import React from "react"; + +type Props = {}; + +export default function PrivacyPolicy({}: Props) { + return ( + + Privacy Policy page + + ); +} diff --git a/src/pages/Information/TermsOfUse.tsx b/src/pages/Information/TermsOfUse.tsx new file mode 100644 index 0000000..6700455 --- /dev/null +++ b/src/pages/Information/TermsOfUse.tsx @@ -0,0 +1,15 @@ +import BaseLayout from "components/BaseLayout"; +import { Footer } from "components/parts/Footer"; +import Header from "components/parts/Header"; +import Typography from "components/typography/Typography"; +import React from "react"; + +type Props = {}; + +export default function TermsOfUse({}: Props) { + return ( + + Terms of use page + + ); +}