From 7beb2ee69dc1b41b72ec79c019b047e168c4f686 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Thu, 6 Nov 2025 14:48:11 +0100 Subject: [PATCH 01/19] landing pages revisited --- frontend/package-lock.json | 19 ++ frontend/package.json | 1 + .../hero-title/hero-title.stories.tsx | 23 ++ .../hero-title/hero-title.styles.ts | 36 ++ .../typography/hero-title/hero-title.tsx | 15 + .../call-to-action-hero.stories.tsx | 45 +++ .../call-to-action-hero.styles.ts | 166 ++++++++++ .../call-to-action-hero.tsx | 36 ++ .../heroes/main-hero/main-hero.stories.tsx | 30 ++ .../heroes/main-hero/main-hero.styles.ts | 84 +++++ .../molecules/heroes/main-hero/main-hero.tsx | 64 ++++ .../secondary-hero/secondary-hero.stories.tsx | 38 +++ .../secondary-hero/secondary-hero.styles.ts | 138 ++++++++ .../heroes/secondary-hero/secondary-hero.tsx | 62 ++++ .../section-hero/section-hero.stories.tsx | 54 +++ .../section-hero/section-hero.styles.ts | 20 ++ .../heroes/section-hero/section-hero.tsx | 72 ++++ .../about-public-page.stories.tsx | 18 + .../about-public-page/about-public-page.tsx | 310 +++++------------- .../home-public-page/CommonStyles.ts | 8 +- .../home-public-page/home-public-page.tsx | 276 +++++----------- 21 files changed, 1087 insertions(+), 428 deletions(-) create mode 100644 frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx create mode 100644 frontend/src/components/design-library/atoms/typography/hero-title/hero-title.styles.ts create mode 100644 frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts create mode 100644 frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.stories.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts create mode 100644 frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.stories.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts create mode 100644 frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx create mode 100644 frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts create mode 100644 frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9c8a9b938..3b9a08c17 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,6 +21,7 @@ "@fortawesome/fontawesome-svg-core": "^1.2.8", "@fortawesome/free-brands-svg-icons": "^5.5.0", "@fortawesome/react-fontawesome": "^0.1.3", + "@lottiefiles/dotlottie-react": "^0.17.6", "@mui/icons-material": "^7.3.1", "@mui/material": "^7.3.1", "@mui/styled-engine-sc": "^5.11.0", @@ -4142,6 +4143,24 @@ "devOptional": true, "license": "MIT" }, + "node_modules/@lottiefiles/dotlottie-react": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-react/-/dotlottie-react-0.17.6.tgz", + "integrity": "sha512-YIa3QYZGPoB+qTdPlpt4cBypdIj2umK/ptD6duaztanbIE8bI+gsqdI8roLPSnNUmIdNwrNM+5zLB7Ly9fu3EA==", + "license": "MIT", + "dependencies": { + "@lottiefiles/dotlottie-web": "0.55.0" + }, + "peerDependencies": { + "react": "^17 || ^18 || ^19" + } + }, + "node_modules/@lottiefiles/dotlottie-web": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-web/-/dotlottie-web-0.55.0.tgz", + "integrity": "sha512-MYpRPxc0630GruhmL5ufTNvjobi9SZG1Zgdr1mr7KCYV1WwMYEO4DobGnR5E+Wbvgp1ChY+7hBKynYobCculGw==", + "license": "MIT" + }, "node_modules/@mdx-js/mdx": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", diff --git a/frontend/package.json b/frontend/package.json index 2323e5980..ec6003d80 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -84,6 +84,7 @@ "@fortawesome/fontawesome-svg-core": "^1.2.8", "@fortawesome/free-brands-svg-icons": "^5.5.0", "@fortawesome/react-fontawesome": "^0.1.3", + "@lottiefiles/dotlottie-react": "^0.17.6", "@mui/icons-material": "^7.3.1", "@mui/material": "^7.3.1", "@mui/styled-engine-sc": "^5.11.0", diff --git a/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx new file mode 100644 index 000000000..f367e9ca1 --- /dev/null +++ b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx @@ -0,0 +1,23 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import HeroTitle from './hero-title'; + +const meta: Meta = { + title: 'Design Library/Atoms/Typography/HeroTitle', + component: HeroTitle, + args: { + children: 'Hero Title', + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; + +export const LongText: Story = { + args: { + children: + 'This is a very long hero title to demonstrate wrapping and responsiveness across different viewports.', + }, +}; \ No newline at end of file diff --git a/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.styles.ts b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.styles.ts new file mode 100644 index 000000000..e713aa817 --- /dev/null +++ b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.styles.ts @@ -0,0 +1,36 @@ +import { styled, Theme } from '@mui/material/styles' + +interface MainTitleProps { + left?: boolean; + center?: boolean; +} + +export const HeroTitleStyled = styled('div', { + shouldForwardProp: (prop) => prop !== 'left' && prop !== 'center' +})(({ theme, left, center }: { theme: Theme } & MainTitleProps) => ({ + textAlign: 'center', + display: 'block', + paddingBottom: 10, + borderBottom: '5px solid black', + width: '60%', + + marginTop: 20, + marginLeft: 'auto', + marginBottom: 20, + marginRight: 'auto', + + ...(left && { + marginRight: '18%' + }), + + ...(center && { + marginRight: '5%', + width: '70%' + }), + + [theme.breakpoints.down('sm')]: { + width: '60%', + margin: '20px auto', + ...(left && { marginLeft: 'auto' }) + } +})) \ No newline at end of file diff --git a/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx new file mode 100644 index 000000000..198714a45 --- /dev/null +++ b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import { HeroTitleStyled } from './hero-title.styles' +import { Typography } from '@mui/material' + +const HeroTitle = ({ children, level }) => { + return ( + + + {children} + + + ) +} + +export default HeroTitle \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx new file mode 100644 index 000000000..6fc9ff26c --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx @@ -0,0 +1,45 @@ +import React from 'react' +import type { Meta, StoryObj } from '@storybook/react' +import CallToActionHero from './call-to-action-hero' + +const meta: Meta = { + title: 'Design Library/Molecules/Heroes/CallToActionHero', + component: CallToActionHero, + args: { + title: 'Be part of our community', + actions: [ + { label: 'Start now', link: '#start', variant: 'contained', color: 'primary', size: 'large' }, + { label: 'Learn more', link: '#learn', variant: 'text', color: 'primary', size: 'large' } + ] + }, + parameters: { + controls: { expanded: true } + } +} +export default meta + +type Story = StoryObj + +export const Default: Story = {} + +export const Secondary: Story = { + args: { + actions: [ + { label: 'Contribute', link: '#contribute', variant: 'contained', color: 'secondary', size: 'large' }, + { label: 'Docs', link: '#docs', variant: 'text', color: 'secondary', size: 'medium' } + ] + } +} + +export const WithLongTitle: Story = { + args: { + title: + 'Join thousands of developers solving issues and getting paid while contributing to open source projects' + } +} + +export const SingleAction: Story = { + args: { + actions: [{ label: 'Get Started', link: '#', variant: 'contained', color: 'primary', size: 'large' }] + } +} diff --git a/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts new file mode 100644 index 000000000..b3640b364 --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts @@ -0,0 +1,166 @@ +import { styled, Theme } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import Button, { ButtonProps } from '@mui/material/Button' +import ListItem from '@mui/material/ListItem' +import { DotLottieReact } from '@lottiefiles/dotlottie-react' + +export const CallToActionHeroStyled = styled('div')(({ theme }) => ({ + position: 'relative', + width: '100%', + height: 500, + overflow: 'hidden', + [theme.breakpoints.down('sm')]: { + height: 400, + } +})) + +export const DotLottieReactStyled = styled(DotLottieReact)(({ theme }) => ({ + position: 'absolute', + top: 120, + left: 0, + width: '100%', + height: '100%', + zIndex: 0, + pointerEvents: 'none', + [theme.breakpoints.down('sm')]: { + top: 220, + width: '100% !important', + height: 'auto !important', + } +})) + + +// Root wrapper +export const Root = styled('div')(() => ({ + flexGrow: 1, + marginTop: 0 +})) + +export const ResponsiveImage = styled('img')(({ theme }) => ({ + [theme.breakpoints.down('sm')]: { + width: '100%' + } +})) + +export const BaseSection = styled('div', { + shouldForwardProp: (prop) => prop !== 'alternative' +})(({ alternative }) => ({ + textAlign: 'center', + padding: '1rem', + ...(alternative && { backgroundColor: '#f1f0ea' }) +})); + +// Section with alternate background +export const AltSection = styled(BaseSection)(({ theme }) => ({ + backgroundColor: theme.palette.primary.contrastText +})) + +// Image helpers +export const HeroImage = styled(ResponsiveImage)(() => ({ + width: '100%' +})) + +export const ImageContainer = styled('div')(() => ({ + marginLeft: 20 +})) + +// Lists +export const SecList = styled('div')(() => ({ + padding: 20 +})) + +export const ListItemTop = styled(ListItem)(() => ({ + marginTop: 0 +})) + +// Buttons +export const GutterTopButton = styled(Button)(() => ({ + marginTop: 20 +})) + +export const MLButton = styled(Button)(() => ({ + marginLeft: 20 +})) + +// Bottom call-to-action section and copy +export const BottomCTASection = styled(BaseSection)(() => ({ + height: 350, + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center' +})) + +export const BottomCopy = styled(Typography)(() => ({ + padding: '0 60px', + lineHeight: 1.4, +})) + +interface MainTitleProps { + left?: boolean; + center?: boolean; +} + +export const MainList = styled('div')(({ theme }) => ({ + textAlign: 'left', + [theme.breakpoints.down('sm')]: { + marginLeft: 0 + } +})) + +export const ShadowImage = styled('img')(({ theme }) => ({ + boxShadow: '1px 1px 3px 2px #ccc', + [theme.breakpoints.down('sm')]: { + maxWidth: '100%' + } +})) + +export const InfoList = styled('div')(({ theme }) => ({ + textAlign: 'left', + marginLeft: '10%', + [theme.breakpoints.down('sm')]: { + marginLeft: 0 + } +})) + +export const MainBanner = styled('div')(({ theme }) => ({ + boxSizing: 'border-box', + marginBottom: '1rem', + backgroundColor: 'black', + backgroundSize: 'cover', + [theme.breakpoints.down('sm')]: { + background: 'none', + backgroundColor: 'black' + } +})) + +interface SectionProps { + alternative?: boolean; +} + +export const Section = styled('div', { + shouldForwardProp: (prop) => prop !== 'alternative' +})(({ alternative }) => ({ + textAlign: 'center', + padding: '1rem', + ...(alternative && { backgroundColor: '#f1f0ea' }) +})); + +export const HeroTitle = styled('div')({}) + +export const HeroSection = styled('div')({ + marginTop: 20, + marginBottom: 20 +}) + +export const HeroContent = styled('div')({ + marginTop: 28, + marginBottom: 20 +}) + +export const HeroActions = styled('div')({ + display: 'flex', + justifyContent: 'flex-start', + alignItems: 'center', + padding: 10 +}) diff --git a/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.tsx b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.tsx new file mode 100644 index 000000000..01fd7ab3f --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.tsx @@ -0,0 +1,36 @@ +import React from 'react' +import { CallToActionHeroStyled, DotLottieReactStyled, BottomCTASection, BottomCopy, GutterTopButton } from './call-to-action-hero.styles' + +const CallToActionHero = ({ + title, + actions +}) => { + return ( + + + + + {title} + + {actions.map((action, index) => ( + + {action.label} + + ))} + + + ) +} + +export default CallToActionHero \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.stories.tsx b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.stories.tsx new file mode 100644 index 000000000..7f57b244f --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.stories.tsx @@ -0,0 +1,30 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { action } from '@storybook/addon-actions' +import MainHero from './main-hero' +import freelancerImage from 'images/collections/collection-flat-build.svg' + +const meta: Meta = { + title: 'Design Library/Molecules/Heroes/MainHero', + component: MainHero, + argTypes: { + mainTitle: { control: 'text' }, + description: { control: 'text' }, + image: { control: 'text' }, + actions: { control: 'object' } + } +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + mainTitle: 'Welcome to Gitpay', + description: 'Ship work faster with bounties and contributors.', + image: freelancerImage, + actions: [ + { label: 'Get Started', variant: 'contained', color: 'primary', onClick: action('get-started') }, + { label: 'Learn More', variant: 'outlined', color: 'secondary', onClick: action('learn-more') } + ] + } +} diff --git a/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts new file mode 100644 index 000000000..a28f0a00f --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts @@ -0,0 +1,84 @@ +import { Button } from '@mui/material'; +import { styled, Theme } from '@mui/material/styles' + +interface MainTitleProps { + left?: boolean; + center?: boolean; +} + +export const ResponsiveImage = styled('img')(({ theme }) => ({ + [theme.breakpoints.down('sm')]: { + width: '100%' + } +})) + +export const ShadowImage = styled('img')(({ theme }) => ({ + boxShadow: '1px 1px 3px 2px #ccc', + [theme.breakpoints.down('sm')]: { + maxWidth: '100%' + } +})) + +export const InfoList = styled('div')(({ theme }) => ({ + textAlign: 'left', + marginLeft: '10%', + [theme.breakpoints.down('sm')]: { + marginLeft: 0 + } +})) + +export const MainBanner = styled('div')(({ theme }) => ({ + boxSizing: 'border-box', + marginBottom: '1rem', + backgroundColor: 'black', + backgroundSize: 'cover', + [theme.breakpoints.down('sm')]: { + background: 'none', + backgroundColor: 'black' + } +})) + +interface SectionProps { + alternative?: boolean; +} + +export const Section = styled('div', { + shouldForwardProp: (prop) => prop !== 'alternative' +})(({ alternative }) => ({ + textAlign: 'center', + padding: '1rem', + ...(alternative && { backgroundColor: '#f1f0ea' }) +})); + +export const HeroTitle = styled('div')({ + lineHeight: 1.2, +}) + +export const HeroSection = styled('div')({ + marginTop: 20, + marginBottom: 20 +}) + +export const HeroContent = styled('div')({ + marginTop: 28, + marginBottom: 20, + '.MuiTypography-root': { + lineHeight: 1.6 + } +}) + +export const HeroActions = styled('div')({ + display: 'flex', + justifyContent: 'flex-start', + alignItems: 'center', + padding: 10 +}) + +// Image helpers +export const HeroImage = styled(ResponsiveImage)(() => ({ + width: '100%' +})) + +export const SpacedButton = styled(Button)(() => ({ + marginRight: 20 +})) \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx new file mode 100644 index 000000000..03dd63fb8 --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx @@ -0,0 +1,64 @@ +import React from 'react' +import { HeroSection, Section, HeroImage, HeroTitle, HeroContent, HeroActions, SpacedButton } from './main-hero.styles' +import { Grid, Typography } from '@mui/material' +import { DotLottieReact } from '@lottiefiles/dotlottie-react'; + +type MainHeroProps = { + mainTitle: React.ReactNode; + description: React.ReactNode; + actions: { + label: React.ReactNode; + variant?: 'text' | 'outlined' | 'contained'; + color?: 'primary' | 'secondary' | 'inherit' | 'success' | 'error' | 'info' | 'warning'; + onClick?: () => void; + }[]; + image?: string; + animation?: string; +} + +const MainHero = ({ + mainTitle, + description, + actions, + image, + animation, +}: MainHeroProps) => { + return ( +
+ + + + {image && } + {animation && } + + + + + {mainTitle} + + + + + {description} + + + + {actions.map((action, index) => ( + + {action.label} + + ))} + + + + +
+ ) +} + +export default MainHero \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.stories.tsx b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.stories.tsx new file mode 100644 index 000000000..ad675a890 --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.stories.tsx @@ -0,0 +1,38 @@ +import type { Meta, StoryObj } from '@storybook/react' +import React from 'react' +import SecondaryHero from './secondary-hero' +import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline' +import SecurityIcon from '@mui/icons-material/Security' +import SupportAgentIcon from '@mui/icons-material/SupportAgent' + +const meta: Meta = { + title: 'Design Library/Molecules/Heroes/SecondaryHero', + component: SecondaryHero +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: { + image: 'https://placehold.co/800x600?text=Secondary+Hero+Image', + title: 'Why choose Gitpay?', + items: [ + { + icon: , + primaryText: 'Easy setup', + secondaryText: 'Get started in minutes with minimal configuration.' + }, + { + icon: , + primaryText: 'Secure by default', + secondaryText: 'Built-in best practices to keep your data safe.' + }, + { + icon: , + primaryText: 'Great support', + secondaryText: 'We’re here to help whenever you need.' + } + ] + } +} diff --git a/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts new file mode 100644 index 000000000..432e35870 --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts @@ -0,0 +1,138 @@ +import { styled, Theme } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import Button, { ButtonProps } from '@mui/material/Button' +import ListItem from '@mui/material/ListItem' + +// Root wrapper +export const Root = styled('div')(() => ({ + flexGrow: 1, + marginTop: 0 +})) + +export const ResponsiveImage = styled('img')(({ theme }) => ({ + [theme.breakpoints.down('sm')]: { + width: '100%' + } +})) + +export const BaseSection = styled('div', { + shouldForwardProp: (prop) => prop !== 'alternative' +})(({ alternative }) => ({ + textAlign: 'center', + padding: '1rem', + ...(alternative && { backgroundColor: '#f1f0ea' }) +})); + +// Section with alternate background +export const AltSection = styled(BaseSection)(({ theme }) => ({ + backgroundColor: theme.palette.primary.contrastText +})) + +// Image helpers +export const HeroImage = styled(ResponsiveImage)(() => ({ + width: '100%' +})) + +export const ImageContainer = styled('div')(() => ({ + marginLeft: 20 +})) + +// Lists +export const SecList = styled('div')(() => ({ + padding: 20 +})) + +export const ListItemTop = styled(ListItem)(() => ({ + marginTop: 0 +})) + +// Buttons +export const GutterTopButton = styled(Button)(() => ({ + marginTop: 20 +})) + +export const MLButton = styled(Button)(() => ({ + marginLeft: 20 +})) + +// Bottom call-to-action section and copy +export const BottomCTASection = styled(BaseSection)(() => ({ + height: 350, + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center' +})) + +export const BottomCopy = styled(Typography)(() => ({ + padding: '0 60px' +})) + +interface MainTitleProps { + left?: boolean; + center?: boolean; +} + +export const MainList = styled('div')(({ theme }) => ({ + textAlign: 'left', + [theme.breakpoints.down('sm')]: { + marginLeft: 0 + } +})) + +export const ShadowImage = styled('img')(({ theme }) => ({ + boxShadow: '1px 1px 3px 2px #ccc', + [theme.breakpoints.down('sm')]: { + maxWidth: '100%' + } +})) + +export const InfoList = styled('div')(({ theme }) => ({ + textAlign: 'left', + marginLeft: '10%', + [theme.breakpoints.down('sm')]: { + marginLeft: 0 + } +})) + +export const MainBanner = styled('div')(({ theme }) => ({ + boxSizing: 'border-box', + marginBottom: '1rem', + backgroundColor: 'black', + backgroundSize: 'cover', + [theme.breakpoints.down('sm')]: { + background: 'none', + backgroundColor: 'black' + } +})) + +interface SectionProps { + alternative?: boolean; +} + +export const Section = styled('div', { + shouldForwardProp: (prop) => prop !== 'alternative' +})(({ alternative }) => ({ + textAlign: 'center', + padding: '1rem', + ...(alternative && { backgroundColor: '#f1f0ea' }) +})); + +export const HeroTitle = styled('div')({}) + +export const HeroSection = styled('div')({ + marginTop: 20, + marginBottom: 20 +}) + +export const HeroContent = styled('div')({ + marginTop: 28, + marginBottom: 20 +}) + +export const HeroActions = styled('div')({ + display: 'flex', + justifyContent: 'flex-start', + alignItems: 'center', + padding: 10 +}) diff --git a/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.tsx b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.tsx new file mode 100644 index 000000000..8e0c2b2f9 --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.tsx @@ -0,0 +1,62 @@ +import React from 'react' +import { Grid } from '@mui/system' +import { List, ListItemIcon, ListItemText, Divider } from '@mui/material' +import HeroTitle from 'design-library/atoms/typography/hero-title/hero-title' +import { AltSection, ImageContainer, ResponsiveImage, SecList, ListItemTop } from './secondary-hero.styles' +import { DotLottieReact } from '@lottiefiles/dotlottie-react' + +type SecondaryHeroProps = { + image?: string; + animation?: string; + title: React.ReactNode; + items: { + icon: React.ReactNode; + primaryText: React.ReactNode; + secondaryText: React.ReactNode; + }[]; +} + +const SecondaryHero = ({ + image, + animation, + title, + items +}: SecondaryHeroProps) => { + return ( + + + {title} + + + + + { animation && } + { image && } + + + + + + {items.map((item, index) => ( + <> + + + {item.icon} + + + + {index < items.length - 1 && } + + ))} + + + + + + ) +} + +export default SecondaryHero \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx new file mode 100644 index 000000000..ffc51ceb6 --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx @@ -0,0 +1,54 @@ +import React from 'react' +import type { Meta, StoryObj } from '@storybook/react' +import SectionHero from './section-hero' +import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline' +import RocketLaunchIcon from '@mui/icons-material/RocketLaunch' +import SecurityIcon from '@mui/icons-material/Security' +import freelancerImage from 'images/collections/collection-flat-community.svg' +import companiesImage from 'images/collections/collection-flat-companies.svg' + +const meta: Meta = { + title: 'Design Library/Molecules/Heroes/SectionHero', + component: SectionHero, + parameters: { + layout: 'fullscreen', + }, +} +export default meta + +type Story = StoryObj + +const items = [ + { + icon: , + primaryText: 'Get started quickly', + secondaryText: 'Kick off your project in minutes with simple setup.', + }, + { + icon: , + primaryText: 'Scale with confidence', + secondaryText: 'Built for performance and growth.', + }, + { + icon: , + primaryText: 'Secure by default', + secondaryText: 'Best practices and protections included.', + }, +] + +export const Default: Story = { + args: { + title: 'Build faster, launch smarter', + image: freelancerImage, + items, + }, +} + +export const Contrast: Story = { + args: { + contrast: true, + title: 'Build faster, launch smarter', + image: companiesImage, + items, + } +} diff --git a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts new file mode 100644 index 000000000..60f69c80b --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts @@ -0,0 +1,20 @@ +import { styled } from '@mui/material/styles' +import { Avatar, ListItem, Typography } from '@mui/material' + +export const Root = styled('div')(({ theme }) => ({ + flexGrow: 1, + marginTop: 0 +})) + +export const ListItemTop = styled(ListItem)(({ theme }) => ({ + marginTop: 20 +})) + +export const HeroContent = styled(Typography)(({ theme }) => ({ + lineHeight: 1.5, +})) + +export const AvatarPrimary = styled(Avatar)(({ theme }) => ({ + backgroundColor: theme.palette.primary.light, + color: theme.palette.primary.main +})) diff --git a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx new file mode 100644 index 000000000..5c1678806 --- /dev/null +++ b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx @@ -0,0 +1,72 @@ +import React from 'react' +import { DotLottieReact } from '@lottiefiles/dotlottie-react'; +import { Grid, Typography, List, ListItemIcon, ListItemText, Container } from '@mui/material' +import { Section, MainTitle, MainList, ResponsiveImage } from '../../../pages/public-pages/home-public-page/CommonStyles' +import { ListItemTop, AvatarPrimary, HeroContent } from './section-hero.styles' + +type SectionHeroProps = { + title: React.ReactNode; + image?: string; + animation?: string; + content?: React.ReactNode | string; + items?: { + icon: React.ReactNode; + primaryText: React.ReactNode; + secondaryText: React.ReactNode; + }[]; + contrast?: boolean; +} + +const SectionHero = ({ + title, + image, + animation, + content, + items, + contrast = false, +}: SectionHeroProps) => { + return ( +
+ + + + + + {title} + + + {content && ( + + {content} + + )} + {items && ( + + + {items.map((item, index) => ( + + + + {item.icon} + + + + + ))} + + + )} + + + {image && } + {animation && } + + + +
+ ) +} +export default SectionHero \ No newline at end of file diff --git a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx index e69de29bb..430bfeee6 100644 --- a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx +++ b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import type { Meta, StoryObj } from '@storybook/react' +import About from './about-public-page' +import { withPublicTemplate } from '../../../../../../.storybook/decorators/withPublicTemplate'; + +const meta: Meta = { + title: 'Design Library/Pages/Public/About', + component: About, + decorators: [withPublicTemplate], + parameters: { + layout: 'fullscreen' + } +} + +export default meta +type Story = StoryObj + +export const Default: Story = {} diff --git a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx index 6c583487a..0df8fd30b 100644 --- a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx @@ -1,247 +1,93 @@ -import React, { useRef } from 'react' +import React from 'react' import { - Grid, - Typography, - List, - ListItemIcon, - ListItemText, Container } from '@mui/material' -import { AccountBalanceWallet, Work, Apps, Assignment, GroupWork } from '@mui/icons-material' -import { useIntl, FormattedMessage } from 'react-intl' -import messages from '../../../../areas/public/features/welcome/legacy/messages' +import { AccountBalanceWallet, Work, Apps, Assignment, GroupWork, AttachMoney } from '@mui/icons-material' +import { FormattedMessage } from 'react-intl' import freelancerImage from 'images/collections/collection-flat-community.svg' import companiesImage from 'images/collections/collection-flat-companies.svg' import teamImage from 'images/welcome-teamwork.png' -import { - MainTitle, - MainList, - ResponsiveImage, - Section -} from '../home-public-page/CommonStyles' - -// new styled components -import { ListItemTop, AvatarPrimary, SectionBgContrast } from './about-public-page.styles' +import SectionHero from 'design-library/molecules/heroes/section-hero/section-hero' const About = () => { - const intl = useIntl() - const ref = useRef(null) return ( <> - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
+ } + image={freelancerImage} + content={} + /> + } + image={teamImage} + content={} + items={[ + { + icon: , + primaryText: , + secondaryText: , + }, + { + icon: , + primaryText: , + secondaryText: , + }, + { + icon: , + primaryText: , + secondaryText: , + }, + { + icon: , + primaryText: , + secondaryText: , + } + ]} + /> + } + image={companiesImage} + content={} + items={[ + { + icon: , + primaryText: , + secondaryText: , + }, + { + icon: , + primaryText: , + secondaryText: , + }, + { + icon: , + primaryText: , + secondaryText: , + }, + { + icon: , + primaryText: , + secondaryText: , + }, + { + icon: , + primaryText: , + secondaryText: , + } + ]} + /> ) } diff --git a/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts b/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts index 367e716a7..075d55250 100644 --- a/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts +++ b/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts @@ -43,8 +43,10 @@ export const MainList = styled('div')(({ theme }) => ({ })) export const ResponsiveImage = styled('img')(({ theme }) => ({ + maxWidth: '100%', + height: 'auto', [theme.breakpoints.down('sm')]: { - width: '100%' + width: '100%', } })) @@ -80,10 +82,10 @@ interface SectionProps { export const Section = styled('div', { shouldForwardProp: (prop) => prop !== 'alternative' -})(({ alternative }) => ({ +})(({ alternative, theme }) => ({ textAlign: 'center', padding: '1rem', - ...(alternative && { backgroundColor: '#f1f0ea' }) + ...(alternative && { backgroundColor: theme.palette.primary.contrastText }) })); export const HeroTitle = styled('div')({}) diff --git a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx index 87eb59cce..e6e99fe99 100644 --- a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx @@ -1,48 +1,20 @@ import React from 'react' -import Grid from '@mui/material/Grid' -import Typography from '@mui/material/Typography' -import Divider from '@mui/material/Divider' -import List from '@mui/material/List' -import ListItemText from '@mui/material/ListItemText' -import ListItemIcon from '@mui/material/ListItemIcon' -import Button from '@mui/material/Button' import { Work, - Archive, CardMembership, - BugReport + Assignment, + AttachMoney, + TaskAlt, } from '@mui/icons-material' import { useIntl, FormattedMessage } from 'react-intl' import { useHistory } from 'react-router-dom' -import messages from '../../../../areas/public/features/welcome/legacy/messages' - -import freelancerImage from 'images/collections/collection-flat-build.svg' import deal from 'images/collections/collection-flat-works.svg' - -import { - MainTitle, - ResponsiveImage, - Section, - HeroSection, - HeroTitle, - HeroContent, - HeroActions -} from './CommonStyles' -import { - AltSection, - BottomCTASection, - BottomCopy, - ImageContainer, - HeroImage, - SecList, - ListItemTop, - GutterTopButton, - MLButton -} from './home-public-page.styles' - +import MainHero from 'design-library/molecules/heroes/main-hero/main-hero' +import SecondaryHero from 'design-library/molecules/heroes/secondary-hero/secondary-hero' +import CallToActionHero from 'design-library/molecules/heroes/call-to-action-hero/call-to-action-hero' const Home = () => { const history = useHistory() @@ -51,166 +23,84 @@ const Home = () => { return ( <> -
- - - - - - - - - - - - - - - - - - - history.push('/signup')} - > - - - - - - -
- - - - - } + description={} + animation={'/lottie/developer-main.lottie'} + actions={[ + { label: 'Learn More', variant: 'outlined', color: 'secondary', onClick: () => history.push('/about') }, + { label: 'Get Started', variant: 'contained', color: 'primary', onClick: () => history.push('/signup') } + ]} + /> + , + primaryText: , + secondaryText: + }, + { + icon: , + primaryText: , + secondaryText: + }, + { + icon: , + primaryText: , + secondaryText: + }, + { + icon: , + primaryText: , + secondaryText: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + }, + ]} + /> + } + actions={[ + { label: , link: '/#/signup', variant: 'contained', color: 'primary', size: 'large' }, + { label: , link: '/#/about', variant: 'text', color: 'primary', size: 'large' } + ]} + /> ) From 7600f1edb9130f0185ba2dd59393ba68d622ccf7 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Thu, 6 Nov 2025 16:19:23 +0100 Subject: [PATCH 02/19] more adjustments to home and about --- .../heroes/section-hero/section-hero.styles.ts | 2 +- .../home-public-page/home-public-page.tsx | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts index 60f69c80b..54cc98b44 100644 --- a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts +++ b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts @@ -7,7 +7,7 @@ export const Root = styled('div')(({ theme }) => ({ })) export const ListItemTop = styled(ListItem)(({ theme }) => ({ - marginTop: 20 + marginTop: 0 })) export const HeroContent = styled(Typography)(({ theme }) => ({ diff --git a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx index e6e99fe99..d80a966f9 100644 --- a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx @@ -34,7 +34,7 @@ const Home = () => { />} animation={'/lottie/developer-main.lottie'} actions={[ - { label: 'Learn More', variant: 'outlined', color: 'secondary', onClick: () => history.push('/about') }, + { label: 'Learn More', variant: 'outlined', color: 'secondary', onClick: () => history.push('/welcome') }, { label: 'Get Started', variant: 'contained', color: 'primary', onClick: () => history.push('/signup') } ]} /> @@ -89,16 +89,27 @@ const Home = () => { defaultMessage="Once the solution is verified, the payout is automatically sent to the contributor's bank account." /> }, + { + icon: , + primaryText: , + secondaryText: + } ]} /> } actions={[ { label: , link: '/#/signup', variant: 'contained', color: 'primary', size: 'large' }, - { label: , link: '/#/about', variant: 'text', color: 'primary', size: 'large' } + { label: , link: '/#/welcome', variant: 'text', color: 'primary', size: 'large' } ]} /> From 897cd7e791018e346cb84025b58a9954b348f88c Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Thu, 6 Nov 2025 23:39:00 +0100 Subject: [PATCH 03/19] about section with animations --- .../hero-title/hero-title.stories.tsx | 8 +-- .../call-to-action-hero.stories.tsx | 1 - .../call-to-action-hero.styles.ts | 8 +-- .../heroes/main-hero/main-hero.styles.ts | 4 +- .../molecules/heroes/main-hero/main-hero.tsx | 2 +- .../secondary-hero/secondary-hero.styles.ts | 2 +- .../section-hero/section-hero.stories.tsx | 18 ++--- .../section-hero/section-hero.styles.ts | 2 +- .../heroes/section-hero/section-hero.tsx | 2 +- .../about-public-page.stories.tsx | 1 - .../about-public-page/about-public-page.tsx | 65 +++++++++---------- .../home-public-page/CommonStyles.ts | 2 +- .../home-public-page/home-public-page.tsx | 5 +- 13 files changed, 58 insertions(+), 62 deletions(-) diff --git a/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx index f367e9ca1..b63c8ee01 100644 --- a/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx +++ b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.stories.tsx @@ -5,8 +5,8 @@ const meta: Meta = { title: 'Design Library/Atoms/Typography/HeroTitle', component: HeroTitle, args: { - children: 'Hero Title', - }, + children: 'Hero Title' + } }; export default meta; @@ -18,6 +18,6 @@ export const Default: Story = {}; export const LongText: Story = { args: { children: - 'This is a very long hero title to demonstrate wrapping and responsiveness across different viewports.', - }, + 'This is a very long hero title to demonstrate wrapping and responsiveness across different viewports.' + } }; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx index 6fc9ff26c..7cb284103 100644 --- a/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx +++ b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.stories.tsx @@ -1,4 +1,3 @@ -import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import CallToActionHero from './call-to-action-hero' diff --git a/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts index b3640b364..6f7b17ee4 100644 --- a/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts +++ b/frontend/src/components/design-library/molecules/heroes/call-to-action-hero/call-to-action-hero.styles.ts @@ -1,4 +1,4 @@ -import { styled, Theme } from '@mui/material/styles' +import { styled } from '@mui/material/styles' import Typography from '@mui/material/Typography' import Button, { ButtonProps } from '@mui/material/Button' import ListItem from '@mui/material/ListItem' @@ -10,7 +10,7 @@ export const CallToActionHeroStyled = styled('div')(({ theme }) => ({ height: 500, overflow: 'hidden', [theme.breakpoints.down('sm')]: { - height: 400, + height: 400 } })) @@ -25,7 +25,7 @@ export const DotLottieReactStyled = styled(DotLottieReact)(({ theme }) => ({ [theme.breakpoints.down('sm')]: { top: 220, width: '100% !important', - height: 'auto !important', + height: 'auto !important' } })) @@ -93,7 +93,7 @@ export const BottomCTASection = styled(BaseSection)(() => ({ export const BottomCopy = styled(Typography)(() => ({ padding: '0 60px', - lineHeight: 1.4, + lineHeight: 1.4 })) interface MainTitleProps { diff --git a/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts index a28f0a00f..8ac8b0eba 100644 --- a/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts +++ b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.styles.ts @@ -1,5 +1,5 @@ import { Button } from '@mui/material'; -import { styled, Theme } from '@mui/material/styles' +import { styled } from '@mui/material/styles' interface MainTitleProps { left?: boolean; @@ -51,7 +51,7 @@ export const Section = styled('div', { })); export const HeroTitle = styled('div')({ - lineHeight: 1.2, + lineHeight: 1.2 }) export const HeroSection = styled('div')({ diff --git a/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx index 03dd63fb8..2fea41c6e 100644 --- a/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx +++ b/frontend/src/components/design-library/molecules/heroes/main-hero/main-hero.tsx @@ -21,7 +21,7 @@ const MainHero = ({ description, actions, image, - animation, + animation }: MainHeroProps) => { return (
diff --git a/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts index 432e35870..71ea09628 100644 --- a/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts +++ b/frontend/src/components/design-library/molecules/heroes/secondary-hero/secondary-hero.styles.ts @@ -1,4 +1,4 @@ -import { styled, Theme } from '@mui/material/styles' +import { styled } from '@mui/material/styles' import Typography from '@mui/material/Typography' import Button, { ButtonProps } from '@mui/material/Button' import ListItem from '@mui/material/ListItem' diff --git a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx index ffc51ceb6..4d24360bf 100644 --- a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx +++ b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.stories.tsx @@ -11,8 +11,8 @@ const meta: Meta = { title: 'Design Library/Molecules/Heroes/SectionHero', component: SectionHero, parameters: { - layout: 'fullscreen', - }, + layout: 'fullscreen' + } } export default meta @@ -22,26 +22,26 @@ const items = [ { icon: , primaryText: 'Get started quickly', - secondaryText: 'Kick off your project in minutes with simple setup.', + secondaryText: 'Kick off your project in minutes with simple setup.' }, { icon: , primaryText: 'Scale with confidence', - secondaryText: 'Built for performance and growth.', + secondaryText: 'Built for performance and growth.' }, { icon: , primaryText: 'Secure by default', - secondaryText: 'Best practices and protections included.', - }, + secondaryText: 'Best practices and protections included.' + } ] export const Default: Story = { args: { title: 'Build faster, launch smarter', image: freelancerImage, - items, - }, + items + } } export const Contrast: Story = { @@ -49,6 +49,6 @@ export const Contrast: Story = { contrast: true, title: 'Build faster, launch smarter', image: companiesImage, - items, + items } } diff --git a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts index 54cc98b44..3ae49a9c1 100644 --- a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts +++ b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.styles.ts @@ -11,7 +11,7 @@ export const ListItemTop = styled(ListItem)(({ theme }) => ({ })) export const HeroContent = styled(Typography)(({ theme }) => ({ - lineHeight: 1.5, + lineHeight: 1.5 })) export const AvatarPrimary = styled(Avatar)(({ theme }) => ({ diff --git a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx index 5c1678806..d6cf9432a 100644 --- a/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx +++ b/frontend/src/components/design-library/molecules/heroes/section-hero/section-hero.tsx @@ -23,7 +23,7 @@ const SectionHero = ({ animation, content, items, - contrast = false, + contrast = false }: SectionHeroProps) => { return (
diff --git a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx index 430bfeee6..3f104c65c 100644 --- a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx +++ b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.stories.tsx @@ -1,4 +1,3 @@ -import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import About from './about-public-page' import { withPublicTemplate } from '../../../../../../.storybook/decorators/withPublicTemplate'; diff --git a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx index 0df8fd30b..0be555f9f 100644 --- a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx @@ -1,7 +1,6 @@ import React from 'react' -import { - Container -} from '@mui/material' + + import { AccountBalanceWallet, Work, Apps, Assignment, GroupWork, AttachMoney } from '@mui/icons-material' import { FormattedMessage } from 'react-intl' import freelancerImage from 'images/collections/collection-flat-community.svg' @@ -15,76 +14,76 @@ const About = () => { return ( <> } - image={freelancerImage} + title={} + animation='/lottie/mission.lottie' content={} /> } - image={teamImage} + title={} + animation='/lottie/startup-life.lottie' content={} items={[ { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: }, { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: }, { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: }, { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: } ]} /> } - image={companiesImage} + title={} + animation='/lottie/coworking.lottie' content={} items={[ { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: }, { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: }, { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: }, { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: }, { icon: , - primaryText: , - secondaryText: , + primaryText: , + secondaryText: } ]} /> diff --git a/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts b/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts index 075d55250..a0e569680 100644 --- a/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts +++ b/frontend/src/components/design-library/pages/public-pages/home-public-page/CommonStyles.ts @@ -46,7 +46,7 @@ export const ResponsiveImage = styled('img')(({ theme }) => ({ maxWidth: '100%', height: 'auto', [theme.breakpoints.down('sm')]: { - width: '100%', + width: '100%' } })) diff --git a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx index d80a966f9..08ead7f88 100644 --- a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx @@ -5,13 +5,12 @@ import { CardMembership, Assignment, AttachMoney, - TaskAlt, + TaskAlt } from '@mui/icons-material' import { useIntl, FormattedMessage } from 'react-intl' import { useHistory } from 'react-router-dom' -import deal from 'images/collections/collection-flat-works.svg' import MainHero from 'design-library/molecules/heroes/main-hero/main-hero' import SecondaryHero from 'design-library/molecules/heroes/secondary-hero/secondary-hero' import CallToActionHero from 'design-library/molecules/heroes/call-to-action-hero/call-to-action-hero' @@ -39,7 +38,7 @@ const Home = () => { ]} /> Date: Fri, 7 Nov 2025 11:06:57 +0100 Subject: [PATCH 04/19] small text adjustments --- .../public-pages/about-public-page/about-public-page.tsx | 3 --- .../public-pages/home-public-page/home-public-page.tsx | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx index 0be555f9f..0b8c981fc 100644 --- a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx @@ -3,9 +3,6 @@ import React from 'react' import { AccountBalanceWallet, Work, Apps, Assignment, GroupWork, AttachMoney } from '@mui/icons-material' import { FormattedMessage } from 'react-intl' -import freelancerImage from 'images/collections/collection-flat-community.svg' -import companiesImage from 'images/collections/collection-flat-companies.svg' -import teamImage from 'images/welcome-teamwork.png' import SectionHero from 'design-library/molecules/heroes/section-hero/section-hero' diff --git a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx index 08ead7f88..30c5ff8d4 100644 --- a/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/home-public-page/home-public-page.tsx @@ -48,11 +48,11 @@ const Home = () => { icon: , primaryText: , secondaryText: }, { @@ -96,7 +96,7 @@ const Home = () => { />, secondaryText: } ]} From 546e995c3c25243aa846874582d14a2dff55b1d3 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Fri, 7 Nov 2025 11:10:49 +0100 Subject: [PATCH 05/19] lint fixes --- .../public-pages/about-public-page/about-public-page.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx index 0b8c981fc..c728b2819 100644 --- a/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/about-public-page/about-public-page.tsx @@ -12,7 +12,7 @@ const About = () => { <> } - animation='/lottie/mission.lottie' + animation="/lottie/mission.lottie" content={ { } - animation='/lottie/startup-life.lottie' + animation="/lottie/startup-life.lottie" content={ { /> } - animation='/lottie/coworking.lottie' + animation="/lottie/coworking.lottie" content={ Date: Fri, 7 Nov 2025 11:25:33 +0100 Subject: [PATCH 06/19] excluding lottie from public ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e8ba20f2f..2c17b2b25 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ coverage # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release frontend/public/ +!/public/lottie/ frontend/build # Dependency directories From 1aa606e3dd31a107ef20c5ea9e1d243ce292a91d Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Fri, 7 Nov 2025 11:34:35 +0100 Subject: [PATCH 07/19] adding lotte animations --- frontend/public/lottie/coworking.lottie | Bin 0 -> 34910 bytes frontend/public/lottie/developer-main.lottie | Bin 0 -> 17409 bytes frontend/public/lottie/developer-team.lottie | Bin 0 -> 36843 bytes frontend/public/lottie/how-it-works.lottie | Bin 0 -> 26680 bytes frontend/public/lottie/mission.lottie | Bin 0 -> 56840 bytes frontend/public/lottie/startup-life.lottie | Bin 0 -> 75223 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 frontend/public/lottie/coworking.lottie create mode 100644 frontend/public/lottie/developer-main.lottie create mode 100644 frontend/public/lottie/developer-team.lottie create mode 100644 frontend/public/lottie/how-it-works.lottie create mode 100644 frontend/public/lottie/mission.lottie create mode 100644 frontend/public/lottie/startup-life.lottie diff --git a/frontend/public/lottie/coworking.lottie b/frontend/public/lottie/coworking.lottie new file mode 100644 index 0000000000000000000000000000000000000000..35c70b01377f3c05dd1f7039d7cc77501be054fa GIT binary patch literal 34910 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 literal 0 HcmV?d00001 diff --git a/frontend/public/lottie/developer-main.lottie b/frontend/public/lottie/developer-main.lottie new file mode 100644 index 0000000000000000000000000000000000000000..d6a1cb9d3da45533322f769613b136efb2a156af GIT binary patch literal 17409 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 literal 0 HcmV?d00001 diff --git a/frontend/public/lottie/developer-team.lottie b/frontend/public/lottie/developer-team.lottie new file mode 100644 index 0000000000000000000000000000000000000000..3d929e3fde080f47ff835f3aa7bdcda41521513d GIT binary patch literal 36843 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%0AsSRVJLcOC|(TQltRi-p=S%9&1 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 literal 0 HcmV?d00001 diff --git a/frontend/public/lottie/mission.lottie b/frontend/public/lottie/mission.lottie new file mode 100644 index 0000000000000000000000000000000000000000..06dd08ccdf1339206934cb050debc4e94706dea8 GIT binary patch literal 56840 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 Mx%si;{l`K54{~n{=l}o! literal 0 HcmV?d00001 diff --git a/frontend/public/lottie/startup-life.lottie b/frontend/public/lottie/startup-life.lottie new file mode 100644 index 0000000000000000000000000000000000000000..01070c1e98b8750de071b00b7af10551ebff6027 GIT binary patch literal 75223 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 literal 0 HcmV?d00001 From d35b296ed4e4f5a2d769f0ce426cb27621c98b39 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Fri, 7 Nov 2025 11:41:51 +0100 Subject: [PATCH 08/19] adding the properly folder for lottie animations --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2c17b2b25..f9424c4c5 100644 --- a/.gitignore +++ b/.gitignore @@ -28,7 +28,7 @@ coverage # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release frontend/public/ -!/public/lottie/ +!/frontend/public/lottie/ frontend/build # Dependency directories From 951f2c3867328d77219244dfc77a00377ee1ae51 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Fri, 7 Nov 2025 16:33:10 +0100 Subject: [PATCH 09/19] moving team page into design library and converting to ts --- .../areas/public/features/team/pages/team.tsx | 12 ++ .../areas/public/features/team/team.js | 162 ----------------- .../features/welcome/legacy/landing-page.js | 2 +- .../areas/public/pages/public-page.tsx | 2 + .../typography/hero-title/hero-title.tsx | 7 +- .../team-card/__tests__/cardTeam.test.js | 2 +- .../cards/team-card/team-card.stories.tsx | 2 +- .../cards/team-card/team-card.styles.ts | 32 ++++ .../team-card/{TeamCard.js => team-card.tsx} | 65 +++---- .../team-public-page.stories.tsx | 26 +++ .../team-public-page.styles.ts | 20 +++ .../team-public-page/team-public-page.tsx | 166 ++++++++++++++++++ frontend/src/containers/team.js | 2 +- frontend/src/index.d.ts | 1 + frontend/src/main/routes.js | 3 - 15 files changed, 292 insertions(+), 212 deletions(-) create mode 100644 frontend/src/components/areas/public/features/team/pages/team.tsx delete mode 100644 frontend/src/components/areas/public/features/team/team.js create mode 100644 frontend/src/components/design-library/molecules/cards/team-card/team-card.styles.ts rename frontend/src/components/design-library/molecules/cards/team-card/{TeamCard.js => team-card.tsx} (66%) create mode 100644 frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.stories.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.styles.ts create mode 100644 frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx diff --git a/frontend/src/components/areas/public/features/team/pages/team.tsx b/frontend/src/components/areas/public/features/team/pages/team.tsx new file mode 100644 index 000000000..3c05baea0 --- /dev/null +++ b/frontend/src/components/areas/public/features/team/pages/team.tsx @@ -0,0 +1,12 @@ +import React from 'react' +import TeamPage from '../../../../../design-library/pages/public-pages/team-public-page/team-public-page' + +const Team = ({ + joinTeamAPICall +}) => { + return ( + + ) +} + +export default Team \ No newline at end of file diff --git a/frontend/src/components/areas/public/features/team/team.js b/frontend/src/components/areas/public/features/team/team.js deleted file mode 100644 index e8f751134..000000000 --- a/frontend/src/components/areas/public/features/team/team.js +++ /dev/null @@ -1,162 +0,0 @@ -import React, { useState } from 'react' -import Bottom from '../../../../shared/bottom/bottom' -import TopBarContainer from '../../../../../containers/topbar' -import TeamCard from 'design-library/molecules/cards/team-card/TeamCard' -import { Grid } from '@mui/material' -import { Page } from 'app/styleguide/components/Page' -import { Section } from '../welcome/components/CommonStyles' -import TextField from '@mui/material/TextField' -import Button from '@mui/material/Button' -import { styled } from '@mui/material/styles' -import Typography from '@mui/material/Typography' -import teamImage from 'images/core-team-page-asset.png' -import imgAlexandre from 'images/teams/headhunter-team-member1.png' -import imgWharley from 'images/teams/wharley-team-member.jpg' -import imgMayna from 'images/teams/core-team-mayna.jpg' -import imgRafael from 'images/teams/profile_rq.jpg' - -function checkEmail (emailAddress) { - let sQtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]' - let sDtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]' - let sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+' - let sQuotedPair = '\\x5c[\\x00-\\x7f]' - let sDomainLiteral = '\\x5b(' + sDtext + '|' + sQuotedPair + ')*\\x5d' - let sQuotedString = '\\x22(' + sQtext + '|' + sQuotedPair + ')*\\x22' - let sDomainRef = sAtom - let sSubDomain = '(' + sDomainRef + '|' + sDomainLiteral + ')' - let sWord = '(' + sAtom + '|' + sQuotedString + ')' - let sDomain = sSubDomain + '(\\x2e' + sSubDomain + ')*' - let sLocalPart = sWord + '(\\x2e' + sWord + ')*' - let sAddrSpec = sLocalPart + '\\x40' + sDomain // complete RFC822 email address spec - let sValidEmail = '^' + sAddrSpec + '$' // as whole string - - let reValidEmail = new RegExp(sValidEmail) - - return reValidEmail.test(emailAddress) -} - -const CoreTeamForm = styled(Grid)(({ theme }) => ({ - marginTop: theme.spacing(3), - marginBottom: theme.spacing(3), - marginRight: theme.spacing(3), - display: 'flex', - flexDirection: 'column', - color: 'white' -})) - -const UnderlineTextField = styled(TextField)(({ theme }) => ({ - '& .MuiInputBase-input': { - color: theme.palette.common.white - }, - marginBottom: 16 -})) - -const recruiterTeam = [ - { - name: 'Alexandre Magno', - description: 'Founder of Gitpay, and senior software engineer for 15+ years, Alexandre is an active open source maintainer, author of Mobile First Boostrap and he help the development community with your blog alexandremagno.net.', - image: imgAlexandre, - linkedinUrl: 'https://www.linkedin.com/in/alexandremagnoteleszimerer/', - githubUrl: 'https://github.com/alexanmtz' - }, - { - name: 'Wharley Ornelas', - description: 'Fullstack developer, with 15+ development experience. First developer to contribute and he helped with the core, and a brazilian developer evangelist', - image: imgWharley, - linkedinUrl: 'https://in.linkedin.com/in/wharley-ornelas-da-rocha-65420932', - githubUrl: 'http://github.com/wharley' - }, - { - name: 'Mayna Thais', - description: 'Project leader with 9+ years of experience. She has worked with software projects and IT infrastructure for many companies. Graduated in Information Systems, MBA in Project Management and Scrum Master certified.', - image: imgMayna, - linkedinUrl: 'https://br.linkedin.com/in/mayna-thais', - githubUrl: 'https://github.com/mthais' - }, - { - name: 'Rafael Quintanilha', - description: 'Software Developer Intern at Gitpay. Graduated in IT Management and with a master\'s in e-business, Rafael has experience working as a digital project manager and now embraces a new career path as a web developer.', - image: imgRafael, - linkedinUrl: 'https://www.linkedin.com/in/rafael-quintanilha/', - githubUrl: 'https://github.com/RafaelQuintanilha18' - } -] - -export default function Team (props) { - const [formData, setFormData] = useState({}) - const [formErrors, setFormErrors] = useState({}) - - const onChange = (event) => { - const name = event.nativeEvent.target.name - const value = event.target.value - setFormData({ ...formData, [name]: value }) - } - - const onSubmit = (event) => { - event.preventDefault() - if (Object.keys(formErrors).length === 0) { - props.joinTeamAPICall(formData.email) - } - } - - const onBlur = (event) => { - !checkEmail(formData.email) ? setFormErrors({ ...formErrors, email: true }) : setFormErrors({}) - } - - return ( - - -

- - - - - -
-
- - - assets - - -
- - - - Join the team! - - - - - Work with the best and be part of the core - - - - - - - - - -
-
-
-
- - - ) -} diff --git a/frontend/src/components/areas/public/features/welcome/legacy/landing-page.js b/frontend/src/components/areas/public/features/welcome/legacy/landing-page.js index e0c358997..1ae176c44 100644 --- a/frontend/src/components/areas/public/features/welcome/legacy/landing-page.js +++ b/frontend/src/components/areas/public/features/welcome/legacy/landing-page.js @@ -15,7 +15,7 @@ import screenImage from 'images/gitpay-explore-task-screenshot.png' import profileImage from 'images/avatar-alexandre.png' import Bottom from 'design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout' import Clientlist from './clientlist' -import TeamCard from 'design-library/molecules/cards/team-card/TeamCard' +import TeamCard from 'design-library/molecules/cards/team-card/team-card' import ContactRecruiterFormContainer from '../../../../../../containers/contact-recruiter-form' import deal from 'images/deal.png' diff --git a/frontend/src/components/areas/public/pages/public-page.tsx b/frontend/src/components/areas/public/pages/public-page.tsx index 0785bf34b..571616259 100644 --- a/frontend/src/components/areas/public/pages/public-page.tsx +++ b/frontend/src/components/areas/public/pages/public-page.tsx @@ -5,6 +5,7 @@ import HomePage from 'design-library/pages/public-pages/home-public-page/home-pu import TaskContainer from '../../../../containers/task' import TaskOrdersContainer from '../../../../containers/task-orders' import WelcomeContainer from '../../../../containers/welcome'; +import TeamContainer from '../../../../containers/team.js' import ProjectPageContainer from '../../../../containers/project-page' import OrganizationPageContainer from '../../../../containers/organization-page' import useCommonActions from '../../../../hooks/use-common-actions'; @@ -46,6 +47,7 @@ const PublicPage = ({ + diff --git a/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx index 198714a45..0d232e129 100644 --- a/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx +++ b/frontend/src/components/design-library/atoms/typography/hero-title/hero-title.tsx @@ -2,7 +2,12 @@ import React from 'react' import { HeroTitleStyled } from './hero-title.styles' import { Typography } from '@mui/material' -const HeroTitle = ({ children, level }) => { +type HeroTitleProps = { + children: React.ReactNode | string, + level?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' +} + +const HeroTitle = ({ children, level }: HeroTitleProps) => { return ( diff --git a/frontend/src/components/design-library/molecules/cards/team-card/__tests__/cardTeam.test.js b/frontend/src/components/design-library/molecules/cards/team-card/__tests__/cardTeam.test.js index ae828941a..384f63743 100644 --- a/frontend/src/components/design-library/molecules/cards/team-card/__tests__/cardTeam.test.js +++ b/frontend/src/components/design-library/molecules/cards/team-card/__tests__/cardTeam.test.js @@ -4,7 +4,7 @@ import React from 'react' import { render, screen } from '@testing-library/react' import { IntlProvider } from 'react-intl' -import TeamCard from '../TeamCard' +import TeamCard from '../team-card' const renderWithIntl = (content, { locale = 'en', messages = {} } = {}) => render( diff --git a/frontend/src/components/design-library/molecules/cards/team-card/team-card.stories.tsx b/frontend/src/components/design-library/molecules/cards/team-card/team-card.stories.tsx index ac5c9acbb..31b39ab8d 100644 --- a/frontend/src/components/design-library/molecules/cards/team-card/team-card.stories.tsx +++ b/frontend/src/components/design-library/molecules/cards/team-card/team-card.stories.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import TeamCard from './TeamCard'; +import TeamCard from './team-card'; export default { title: 'Design Library/Molecules/Cards/TeamCard', diff --git a/frontend/src/components/design-library/molecules/cards/team-card/team-card.styles.ts b/frontend/src/components/design-library/molecules/cards/team-card/team-card.styles.ts new file mode 100644 index 000000000..f38cae707 --- /dev/null +++ b/frontend/src/components/design-library/molecules/cards/team-card/team-card.styles.ts @@ -0,0 +1,32 @@ +import { styled } from '@mui/material/styles' +import { Card, CardMedia } from '@mui/material' + +export const Wrapper = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + flexGrow: 1, + justifyContent: 'center' +})) + +export const Root = styled('div')(({ theme }) => ({ + display: 'flex', + justifyContent: 'center', + flexDirection: 'row', + flexFlow: 'wrap', + [theme.breakpoints.down('sm')]: { + flexDirection: 'column' + } +})) + +export const StyledCard = styled(Card)(({ theme }) => ({ + maxWidth: 400, + minWidth: 350, + [theme.breakpoints.down('sm')]: { + minWidth: 0 + }, + margin: 40 +})) + +export const Media = styled(CardMedia)(({ theme }) => ({ + height: 220 +})) \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/cards/team-card/TeamCard.js b/frontend/src/components/design-library/molecules/cards/team-card/team-card.tsx similarity index 66% rename from frontend/src/components/design-library/molecules/cards/team-card/TeamCard.js rename to frontend/src/components/design-library/molecules/cards/team-card/team-card.tsx index 6d750cdbb..46d8d0524 100644 --- a/frontend/src/components/design-library/molecules/cards/team-card/TeamCard.js +++ b/frontend/src/components/design-library/molecules/cards/team-card/team-card.tsx @@ -1,56 +1,37 @@ import React from 'react' -import { FormattedMessage } from 'react-intl' -import { styled } from '@mui/material/styles' -import Card from '@mui/material/Card' import CardActionArea from '@mui/material/CardActionArea' import CardActions from '@mui/material/CardActions' import CardContent from '@mui/material/CardContent' -import CardMedia from '@mui/material/CardMedia' -import Button from '@mui/material/Button' import Typography from '@mui/material/Typography' import LinkedInIcon from '@mui/icons-material/LinkedIn' import GitHubIcon from '@mui/icons-material/GitHub' +import Button from '@mui/material/Button' +import { + Wrapper, + Root, + StyledCard, + Media +} from './team-card.styles' -const Wrapper = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - flexGrow: 1, - justifyContent: 'center' -})) - -const Root = styled('div')(({ theme }) => ({ - display: 'flex', - justifyContent: 'center', - flexDirection: 'row', - flexFlow: 'wrap', - [theme.breakpoints.down('sm')]: { - flexDirection: 'column' - } -})) - -const StyledCard = styled(Card)(({ theme }) => ({ - maxWidth: 400, - minWidth: 350, - [theme.breakpoints.down('sm')]: { - minWidth: 0 - }, - margin: 40 -})) - -const Media = styled(CardMedia)(({ theme }) => ({ - height: 220 -})) - -export default function TeamCard (props) { - const { data } = props +type TeamCardProps = { + title?: React.ReactNode | string, + data: Array<{ + name: string, + description: string, + image: string, + linkedinUrl?: string, + githubUrl?: string + }> +} +export default function TeamCard ({ + title, + data +}: TeamCardProps) { return ( - - + + { title } { data && data.map(member => { diff --git a/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.stories.tsx new file mode 100644 index 000000000..1eaec406c --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from '@storybook/react' +import Team from './team-public-page' +import { action } from '@storybook/addon-actions' +import { withPublicTemplate } from '../../../../../../.storybook/decorators/withPublicTemplate' + +const meta: Meta = { + title: 'Design Library/Pages/Public/Team', + component: Team, + decorators: [ + withPublicTemplate + ] +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + joinTeamAPICall: (email: string) => { + // stub API call + console.log('joinTeamAPICall invoked with:', email) + action('joinTeamAPICall')(email) + } + } +} diff --git a/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.styles.ts b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.styles.ts new file mode 100644 index 000000000..a9b26172a --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.styles.ts @@ -0,0 +1,20 @@ +import { styled } from '@mui/material/styles' +import { Grid } from '@mui/material' +import TextField from '@mui/material/TextField' + +export const CoreTeamForm = styled(Grid)(({ theme }) => ({ + marginTop: theme.spacing(3), + marginBottom: theme.spacing(3), + marginRight: theme.spacing(3), + display: 'flex', + flexDirection: 'column', + color: 'white' +})) + +export const UnderlineTextField = styled(TextField)(({ theme }) => ({ + '& .MuiInputBase-input': { + color: theme.palette.common.white, + border: `1px solid ${theme.palette.common.white}` + }, + marginBottom: 16 +})) diff --git a/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx new file mode 100644 index 000000000..a8ad235c8 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx @@ -0,0 +1,166 @@ +import React, { useState } from 'react' +import TeamCard from 'design-library/molecules/cards/team-card/team-card' +import { Grid } from '@mui/material' +import { Page } from '../../../../../styleguide/components/Page' +import { Section } from '../home-public-page/CommonStyles' +import Button from '@mui/material/Button' +import Typography from '@mui/material/Typography' +import teamImage from 'images/core-team-page-asset.png' +import imgAlexandre from 'images/teams/headhunter-team-member1.png' +import imgWharley from '../../../../../images/teams/wharley-team-member.jpg' +import imgMayna from '../../../../../images/teams/core-team-mayna.jpg' +import imgRafael from '../../../../../images/teams/profile_rq.jpg' +import { FormattedMessage } from 'react-intl' +import { CoreTeamForm, UnderlineTextField } from './team-public-page.styles' +import HeroTitle from 'design-library/atoms/typography/hero-title/hero-title' + +function checkEmail(emailAddress) { + let sQtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]' + let sDtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]' + let sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+' + let sQuotedPair = '\\x5c[\\x00-\\x7f]' + let sDomainLiteral = '\\x5b(' + sDtext + '|' + sQuotedPair + ')*\\x5d' + let sQuotedString = '\\x22(' + sQtext + '|' + sQuotedPair + ')*\\x22' + let sDomainRef = sAtom + let sSubDomain = '(' + sDomainRef + '|' + sDomainLiteral + ')' + let sWord = '(' + sAtom + '|' + sQuotedString + ')' + let sDomain = sSubDomain + '(\\x2e' + sSubDomain + ')*' + let sLocalPart = sWord + '(\\x2e' + sWord + ')*' + let sAddrSpec = sLocalPart + '\\x40' + sDomain // complete RFC822 email address spec + let sValidEmail = '^' + sAddrSpec + '$' // as whole string + + let reValidEmail = new RegExp(sValidEmail) + + return reValidEmail.test(emailAddress) +} + +const currentTeam = [ + { + name: 'Alexandre Magno', + description: 'Founder of Gitpay, and senior software engineer for 15+ years, Alexandre is an active open source maintainer, author of Mobile First Boostrap and he help the development community with your blog alexandremagno.net.', + image: imgAlexandre, + linkedinUrl: 'https://www.linkedin.com/in/alexandremagnoteleszimerer/', + githubUrl: 'https://github.com/alexanmtz' + }, +] + +const pastContributors = [ + { + name: 'Wharley Ornelas', + description: 'Fullstack developer, with 15+ development experience. First developer to contribute and he helped with the core, and a brazilian developer evangelist', + image: imgWharley, + linkedinUrl: 'https://in.linkedin.com/in/wharley-ornelas-da-rocha-65420932', + githubUrl: 'http://github.com/wharley' + }, + { + name: 'Mayna Thais', + description: 'Project leader with 9+ years of experience. She has worked with software projects and IT infrastructure for many companies. Graduated in Information Systems, MBA in Project Management and Scrum Master certified.', + image: imgMayna, + linkedinUrl: 'https://br.linkedin.com/in/mayna-thais', + githubUrl: 'https://github.com/mthais' + }, + { + name: 'Rafael Quintanilha', + description: 'Software Developer Intern at Gitpay. Graduated in IT Management and with a master\'s in e-business, Rafael has experience working as a digital project manager and now embraces a new career path as a web developer.', + image: imgRafael, + linkedinUrl: 'https://www.linkedin.com/in/rafael-quintanilha/', + githubUrl: 'https://github.com/RafaelQuintanilha18' + } +] + +type TeamProps = { + joinTeamAPICall: (email: string) => void +} + +export default function Team({ + joinTeamAPICall +}: TeamProps) { + const [formData, setFormData] = useState<{ email: string }>({ email: '' }) + const [formErrors, setFormErrors] = useState<{ email?: boolean }>({}) + + const onChange = (event) => { + const name = event.nativeEvent.target.name + const value = event.target.value + setFormData({ ...formData, [name]: value }) + } + + const onSubmit = (event) => { + event.preventDefault() + if (Object.keys(formErrors).length === 0) { + joinTeamAPICall(formData.email) + } + } + + const onBlur = (event) => { + !checkEmail(formData.email) ? setFormErrors({ ...formErrors, email: true }) : setFormErrors({}) + } + + return ( + + + + +
+ + + } + data={currentTeam} + /> + + + } + data={pastContributors} + /> + + +
+
+
+ + + assets + + +
+ + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/containers/team.js b/frontend/src/containers/team.js index 088f067eb..5f04b16fd 100644 --- a/frontend/src/containers/team.js +++ b/frontend/src/containers/team.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import Team from '../components/areas/public/features/team/team' +import Team from '../components/areas/public/features/team/pages/team' import { joinTeam } from '../actions/teamActions' const mapStateToProps = (state, ownProps) => { diff --git a/frontend/src/index.d.ts b/frontend/src/index.d.ts index 724425b89..2c92e2e01 100644 --- a/frontend/src/index.d.ts +++ b/frontend/src/index.d.ts @@ -1,4 +1,5 @@ declare module '*.png'; +declare module '*.jpg'; declare module '*.svg' { const content: string; export default content; diff --git a/frontend/src/main/routes.js b/frontend/src/main/routes.js index d86aa06a1..59207c767 100644 --- a/frontend/src/main/routes.js +++ b/frontend/src/main/routes.js @@ -1,12 +1,10 @@ import React from 'react' import { Route, HashRouter, Switch, Redirect } from 'react-router-dom' - import PrivateRoute from '../components/areas/private/components/session/private-route' import PublicPageContainer from '../containers/public-container' import Session from '../components/areas/private/components/session/session' import ProfileContainer from '../containers/profile' import AccountActivation from '../containers/account-activation' -import TeamContainer from '../containers/team.js' import LoginPageContainer from '../containers/login-page' import FourOFour from '../components/design-library/pages/public-pages/four-o-four-public-page/four-o-four-public-page' import Stats from '../components/areas/public/features/stats/Stats-main-page' @@ -24,7 +22,6 @@ export default props => ( {/* Private area needs to appear before the broad "/" route */} - From 191cf898bbdbed5ad108cf370eff70d729b65017 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Fri, 7 Nov 2025 16:37:12 +0100 Subject: [PATCH 10/19] lint fixes --- .../team-public-page/team-public-page.tsx | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx index a8ad235c8..9c445f08f 100644 --- a/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/team-public-page/team-public-page.tsx @@ -41,7 +41,7 @@ const currentTeam = [ image: imgAlexandre, linkedinUrl: 'https://www.linkedin.com/in/alexandremagnoteleszimerer/', githubUrl: 'https://github.com/alexanmtz' - }, + } ] const pastContributors = [ @@ -97,20 +97,20 @@ export default function Team({ return ( - - + +
- + } + title={} data={currentTeam} /> - + } + title={} data={pastContributors} /> @@ -120,19 +120,19 @@ export default function Team({
- assets + assets
- + - + @@ -140,18 +140,18 @@ export default function Team({ required value={formData.email} error={formErrors.email} - id='email' + id="email" fullWidth - label='Email Address' - name='email' - color='primary' - autoComplete='email' + label="Email Address" + name="email" + color="primary" + autoComplete="email" /> - From ae4370094bb7db95ecb5a16d12e7f08cff9b3c3a Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Fri, 7 Nov 2025 16:40:28 +0100 Subject: [PATCH 11/19] lint fixes --- .../bottom-bar-layout/bottom-bar-layout.tsx | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx b/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx index 489230296..d77159235 100644 --- a/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx +++ b/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx @@ -23,15 +23,13 @@ import CookiePolicy from '../../../../../areas/private/components/session/cookie import logoCompleteGray from 'images/logo-complete-gray.png' import logoWorknEnjoy from 'images/worknenjoy-logo.png' -// Styles were migrated to styled components in bottom.styles.ts - -const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0}, getInfo }) => { +const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0 }, getInfo }) => { const { tasks, bounties, users } = info return ( - + - + @@ -46,8 +44,8 @@ const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0}, getInfo }) => { window.location.assign('/#/welcome') } + style={{ display: 'block', width: '100%' }} + onClick={() => window.location.assign('/#/welcome')} > { window.location.assign('/#/pricing') } + style={{ display: 'block', width: '100%' }} + onClick={() => window.location.assign('/#/pricing')} > { window.location.assign('/#/team') } + style={{ display: 'block', width: '100%' }} + onClick={() => window.location.assign('/#/team')} > { window.open('https://docs.gitpay.me/en') } + style={{ display: 'block', width: '100%' }} + onClick={() => window.open('https://docs.gitpay.me/en')} > { window.location.assign('/#/tasks/open') } + style={{ display: 'block', width: '100%' }} + onClick={() => window.location.assign('/#/tasks/open')} > { classes={{}} title="Legal" header="Privacy policy" - subtitle={ 'Privacy Policy' } + subtitle={'Privacy Policy'} content={ - + } /> { classes={{}} title="Legal" header="Terms of Service" - subtitle={ 'Terms of Service' } + subtitle={'Terms of Service'} content={ } @@ -144,9 +142,9 @@ const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0}, getInfo }) => { classes={{}} title="Legal" header="Cookie Policy" - subtitle={ 'Cookie Policy' } + subtitle={'Cookie Policy'} content={ - + } /> @@ -165,20 +163,20 @@ const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0}, getInfo }) => { -
+
- +
{ />
- + -
- +
+ worknenjoy, Inc.
MA: 9450 SW Gemini Dr @@ -201,10 +199,10 @@ const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0}, getInfo }) => {
- + - + ) } From 8c8f5136064116509a82a84e0d7284b9d0640fbb Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Fri, 7 Nov 2025 21:37:31 +0100 Subject: [PATCH 12/19] spliting bottom bar main components into design library and adjusting styles --- .../components/BottomSectionDialog.tsx | 69 --- .../features/welcome/components/Info.js | 46 -- .../features/welcome/components/OurStack.js | 69 --- .../bottom-section-dialog.styles.ts | 12 - .../features/welcome/components/cubes.js | 167 ------- .../features/welcome/legacy/clientlist.js | 80 ---- .../features/welcome/legacy/consulting.js | 127 ------ .../welcome/legacy/contact-recruiter-form.js | 224 ---------- .../features/welcome/legacy/country-list.js | 36 -- .../public/features/welcome/legacy/home.js | 232 ---------- .../welcome/legacy/how-it-works-company.js | 138 ------ .../welcome/legacy/how-it-works-people.js | 141 ------ .../features/welcome/legacy/landing-page.js | 406 ------------------ .../features/welcome/legacy/messages.js | 292 ------------- .../legacy/terms-of-service-company.js | 114 ----- .../welcome/legacy/terms-of-service-people.js | 114 ----- .../public/features/welcome/legacy/welcome.js | 256 ----------- .../welcome/legacy/which-companies.js | 134 ------ .../features/welcome/legacy/who-subscribes.js | 114 ----- .../features/welcome/legacy/workflow.js | 138 ------ .../content/cookie-policy/cookie-policy.tsx | 81 ++++ .../bottom-section-dialog}/CommonStyles.js | 4 +- .../bottom-section-dialog.styles.ts | 106 +---- .../bottom-section-dialog.tsx | 72 ++-- .../vertical-menu-list.stories.tsx | 24 ++ .../vertical-menu-list.styles.ts} | 0 .../vertical-menu-list/vertical-menu-list.tsx | 54 +++ .../bottom-bar-layout/bottom-bar-layout.tsx | 162 ++----- .../pricing-public-page.tsx | 16 +- 29 files changed, 245 insertions(+), 3183 deletions(-) delete mode 100644 frontend/src/components/areas/public/features/welcome/components/BottomSectionDialog.tsx delete mode 100644 frontend/src/components/areas/public/features/welcome/components/Info.js delete mode 100644 frontend/src/components/areas/public/features/welcome/components/OurStack.js delete mode 100644 frontend/src/components/areas/public/features/welcome/components/bottom-section-dialog.styles.ts delete mode 100644 frontend/src/components/areas/public/features/welcome/components/cubes.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/clientlist.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/consulting.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/contact-recruiter-form.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/country-list.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/home.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/how-it-works-company.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/how-it-works-people.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/landing-page.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/messages.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-company.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-people.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/welcome.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/which-companies.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/who-subscribes.js delete mode 100644 frontend/src/components/areas/public/features/welcome/legacy/workflow.js create mode 100644 frontend/src/components/design-library/molecules/content/cookie-policy/cookie-policy.tsx rename frontend/src/components/{areas/public/features/welcome/components => design-library/molecules/dialogs/bottom-section-dialog}/CommonStyles.js (95%) create mode 100644 frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx rename frontend/src/components/{areas/public/features/welcome/legacy/github-app.js => design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts} (100%) create mode 100644 frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx diff --git a/frontend/src/components/areas/public/features/welcome/components/BottomSectionDialog.tsx b/frontend/src/components/areas/public/features/welcome/components/BottomSectionDialog.tsx deleted file mode 100644 index 1af73ce3b..000000000 --- a/frontend/src/components/areas/public/features/welcome/components/BottomSectionDialog.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react' -import { - ListItem, - ListItemButton, - Typography, - Dialog, - AppBar, - Toolbar, - IconButton, -} from '@mui/material' - -import { - Close, -} from '@mui/icons-material' - -import { InfoList } from './CommonStyles' -import { AppBar as AppBarStyles, AppBarHeader } from './bottom-section-dialog.styles' - - -const BottomSectionDialog = ({ - classes, - header, - title, - subtitle, - content, -}) => { - - const [ open, setOpen ] = React.useState(false) - - return ( - - - setOpen(true) } - component='div' - style={ { display: 'block', width: '100%' } } - > - {header} - - - setOpen(false) } - > - - - setOpen(false) } - aria-label='Close' - > - - - - {title} - - - - {content} - - - - - ) -} - -export default BottomSectionDialog \ No newline at end of file diff --git a/frontend/src/components/areas/public/features/welcome/components/Info.js b/frontend/src/components/areas/public/features/welcome/components/Info.js deleted file mode 100644 index b0ad7cd41..000000000 --- a/frontend/src/components/areas/public/features/welcome/components/Info.js +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useEffect } from 'react' -import { FormattedMessage } from 'react-intl' -import styled from 'styled-components' - -import { - Chip, - Typography -} from '@mui/material' - -const Content = styled.span` - margin-top: 5px; - padding-bottom: 10px; - color: white; - text-align: left; - display: inline-block; -` - -const Info = ({ info, tasks, bounties, users }) => { - useEffect(() => { - info() - }, [info]) - - const stats = { - tasks: { value: tasks || '0' }, - bounties: { value: '$' + (bounties || '0') }, - users: { value: users || '0' } - } - - return ( - - - } />, - bounties: , - users: } /> } /> - } } /> - - - ) -} - -export default Info diff --git a/frontend/src/components/areas/public/features/welcome/components/OurStack.js b/frontend/src/components/areas/public/features/welcome/components/OurStack.js deleted file mode 100644 index 8b8ce3ee7..000000000 --- a/frontend/src/components/areas/public/features/welcome/components/OurStack.js +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react' -import { FormattedMessage } from 'react-intl' -import styled from 'styled-components' - -import { - Chip, - Typography, -} from '@mui/material' - -import PropTypes from 'prop-types' - -const data = [ - { label: 'React.js', url: 'https://reactjs.org/' }, - { label: 'Material-ui', url: 'https://material-ui.com/' }, - { label: 'Node.js', url: 'https://nodejs.org' }, - { label: 'Postgres', url: 'https://www.postgresql.org/' }, - { label: 'Heroku', url: 'http://heroku.com/' }, - { label: 'Github', url: 'https://github.com' } -] - -export const Technology = styled(Chip)` - && { - margin: 10px; - font-weight: bold; - } -` - -export const Stack = styled.div` - margin-top: 5px; -` - -export const Content = styled.div` - margin-top: 20px; - padding-bottom: 10px; - color: black; - text-align: center; -` - -const handleClick = url => event => { - window.location.href = url -} - -const OurStack = ({ technologies }) => ( - - - - - { technologies.map((technology, index) => - () - ) - } - - - -) - -OurStack.propTypes = { - technologies: PropTypes.array -} - -OurStack.defaultProps = { - technologies: data -} - -export default OurStack diff --git a/frontend/src/components/areas/public/features/welcome/components/bottom-section-dialog.styles.ts b/frontend/src/components/areas/public/features/welcome/components/bottom-section-dialog.styles.ts deleted file mode 100644 index 5fea6cb06..000000000 --- a/frontend/src/components/areas/public/features/welcome/components/bottom-section-dialog.styles.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { styled } from '@mui/material/styles' -import MuiAppBar from '@mui/material/AppBar' -import { Typography } from '@mui/material' - -export const AppBarHeader = styled(Typography)(({ theme }) => ({ - color: theme.palette.primary.main -})) - -export const AppBar = styled(MuiAppBar)({ - height: '100%', - width: '100%' -}) \ No newline at end of file diff --git a/frontend/src/components/areas/public/features/welcome/components/cubes.js b/frontend/src/components/areas/public/features/welcome/components/cubes.js deleted file mode 100644 index 34f5e4291..000000000 --- a/frontend/src/components/areas/public/features/welcome/components/cubes.js +++ /dev/null @@ -1,167 +0,0 @@ -import React, { useEffect } from 'react' -import * as THREE from 'three' - -const cubeX = (x, y, z, edges, scene) => { - const cube = new THREE.LineSegments(edges, - new THREE.LineBasicMaterial({ - color: '#58d7b2', - opacity: Math.random(), - transparent: true, - linewidth: 3, - linecap: 'round', // ignored by WebGLRenderer - linejoin: 'round' // ignored by WebGLRenderer - })) - cube.position.set(x, y, z) - cube.scale.x = 0.01 - cube.scale.y = 0.01 - cube.scale.z = 0.01 - scene.add(cube) // adds the cube to the scene - return cube -} - -const cubeRotateAndScaleUp = (cube) => { - cube.rotation.z += 0.005 - cube.rotation.x += 0.005 - cube.rotation.y += 0.005 // Runs every frame giving it the animation - cube.scale.x += 0.001 - cube.scale.y += 0.001 - cube.scale.z += 0.001 -} - -const cubeRotateAndScaleDown = (cube) => { - cube.material.opacity -= 0.0002 - cube.material.opacity -= 0.0002 -} - -const cubeReset = (cube) => { - cube.material.opacity = 1 - cube.scale.x = 0.01 - cube.scale.y = 0.01 - cube.scale.z = 0.01 -} - -const Cubes = ({ children }) => { - useEffect(() => { - const height = 285 - const width = window.innerWidth - - // 3 must haves - SCENE , CAMERA, RENDERER - - let scene = new THREE.Scene() // Creates a new scene - - let camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000) // Creates a camera and passes (field of view, aspect ratio, near clipping plane, far clipping plane) - camera.position.set(0, 0, 5)// moves the camera back some so we won't be inside of the cube - camera.lookAt(scene.position) // makes the camera always point toward the scene - scene.add(camera) - - let light = new THREE.PointLight('rgb(88,215,178)') - light.position.set(10, 0, 10) - scene.add(light) - - let renderer = new THREE.WebGLRenderer() - renderer.setSize(width, height) // sets size of render to the screen size - renderer.domElement.style.position = 'absolute' - renderer.domElement.style.top = 0 - renderer.domElement.style.zIndex = -1 - renderer.domElement.style.height = '400px' - document.getElementById('cube-placement').appendChild(renderer.domElement) // Renders a canvas tag to the DOM - - const geometry = new THREE.BoxGeometry() - const sphereGeometry = new THREE.SphereGeometry(2, 32, 32, 0, 6.3, 0, 3) - const edges = new THREE.EdgesGeometry(geometry) - const sphereEdges = new THREE.EdgesGeometry(sphereGeometry) - const cubes = [ - [15, 0, 0, 0], - [15, -3, -1, 0], - [18, 1, 0, 0], - [19, -3, -1, 0], - [-19, -3, -1, 0], - [16, -2, 1, 0], - [-15, 0, 0, 0], - [-15, 1, 1, 0], - [-18, -1, 0, 0], - [-16, 2, -1, 0], - [-17, 1, 0, 0], - [-16, -2, -1, 0], - [-16, 2, 0, 0], - [15, 0, 0, 0], - [15, -3, -1, 0], - [18, 1, 0, 0], - [-15, 0, 0, 0], - [-15, 1, 1, 0], - [-18, -1, 0, 0], - [-16, 2, -1, 0], - [-17, 1, 0, 0], - [-16, -2, -1, 0], - [-16, 2, 0, 0], - [15, 0, 0, 0], - [15, -3, -1, 0], - [18, 1, 0, 0], - [16, -2, 1, 0], - [-15, 0, 0, 0], - [-15, 1, 1, 0], - [-18, -1, 0, 0], - [-16, 2, -1, 0], - [-17, 1, 0, 0], - [-16, -2, -1, 0], - [-16, 2, 0, 0], - [15, 0, 0, 0], - [15, -3, -1, 0], - [18, 1, 0, 0], - [16, -2, 1, 0], - [-15, 0, 0, 0], - [-15, 1, 1, 0], - [-18, -1, 0, 0], - [-16, 2, -1, 0], - [-17, 1, 0, 0], - [-16, -2, -1, 0], - [-16, 2, 0, 0], - [15, 0, 0, 0], - [15, -3, -1, 0], - [18, 1, 0, 0], - [16, -2, 1, 0], - [-15, 0, 0, 0], - [-15, 1, 1, 0], - [-18, -1, 0, 0], - [-16, 2, -1, 0], - [-17, 1, 0, 0], - [-16, -2, -1, 0], - [-16, 2, 0, 0] - - ] - let cubesInstances = [] - const edgetTypes = [edges, sphereEdges] - for (let i = 0; i < cubes.length; i++) { - cubesInstances[i] = cubeX(cubes[i][0], cubes[i][1], cubes[i][2], edgetTypes[cubes[i][3]], scene) - } - - // Render loop to display cube - function render () { - const animation = window.requestAnimationFrame(render) // requestAnimationFrame will pause when the user navigates to a new tab - - for (let i = 0; i < cubesInstances.length; i++) { - cubeRotateAndScaleUp(cubesInstances[i]) - cubeRotateAndScaleDown(cubesInstances[i]) - } - - if (cubesInstances[0].material.opacity < 0) { - window.cancelAnimationFrame(animation) - for (let i = 0; i < cubesInstances.length; i++) { - cubeReset(cubesInstances[i]) - } - render() - } - renderer.render(scene, camera) - } - - render() - }, []) - - return ( -
- { children } -
- ) -} - -export default Cubes diff --git a/frontend/src/components/areas/public/features/welcome/legacy/clientlist.js b/frontend/src/components/areas/public/features/welcome/legacy/clientlist.js deleted file mode 100644 index 6b55ec0a7..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/clientlist.js +++ /dev/null @@ -1,80 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' - -import { Card, Grid, Typography } from '@mui/material' -import { styled } from '@mui/material/styles' - -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - MainTitle, - ResponsiveImage -} from '../components/CommonStyles' - -const Layout = styled('div')(({ theme }) => ({ - width: 'auto', - marginBottom: theme.spacing(6), - marginTop: theme.spacing(2), - [theme.breakpoints.up(900 + theme.spacing(3) * 2)]: { - width: '100%' - }, - textAlign: 'center' -})) - -const HeroContent = styled('div')(({ theme }) => ({ - maxWidth: 600, - margin: '0 auto', - padding: `0 0 ${theme.spacing(4)}px`, -})) - -import clientimg1 from 'images/clients/electron-logo.png' -import clientimg2 from 'images/clients/etherpad-logo.png' -import clientimg3 from 'images/clients/sitespeedio-logo.png' - -const clients = [ - { - title: 'Electron', - img: clientimg1, - link: 'https://www.electron.build/' - }, - { - title: 'Etherpad', - img: clientimg2, - link: 'https://etherpad.org/' - }, - { - title: 'Sitespeed.io', - img: clientimg3, - link: 'https://sitespeed.io' - }, -] -class Clientlist extends Component { - render () { - const { } = this.props - - return ( - - - - - - - - - - { clients.map(client => ( - - - - - - )) } - - - ) - } -} - -Clientlist.propTypes = {} - -export default injectIntl(Clientlist) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/consulting.js b/frontend/src/components/areas/public/features/welcome/legacy/consulting.js deleted file mode 100644 index f59445357..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/consulting.js +++ /dev/null @@ -1,127 +0,0 @@ -import React, { useState, useEffect } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Work, - AccountBalanceWallet, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -const Consulting = ({ classes, ...props }) => { - const [open, setOpen] = useState(false) - - const handleClickOpen = () => { - setOpen(true) - } - - const handleClose = () => { - setOpen(false) - } - - useEffect(() => { - // Component did mount functionality here - }, []) - - return ( - - - - {(msg) => ( - - )} - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- ) -} - -Consulting.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(Consulting) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/contact-recruiter-form.js b/frontend/src/components/areas/public/features/welcome/legacy/contact-recruiter-form.js deleted file mode 100644 index 522e943b8..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/contact-recruiter-form.js +++ /dev/null @@ -1,224 +0,0 @@ -import React, { useState } from 'react' -import Avatar from '@mui/material/Avatar' -import Button from '@mui/material/Button' -import CssBaseline from '@mui/material/CssBaseline' -import TextField from '@mui/material/TextField' -import CircularProgress from '@mui/material/CircularProgress' -import Grid from '@mui/material/Grid' -import { MuiTelInput } from 'mui-tel-input' -import { - ContactMailOutlined -} from '@mui/icons-material' -import Typography from '@mui/material/Typography' -import { styled } from '@mui/material/styles' -import Container from '@mui/material/Container' -import CountryList from './country-list' - -function checkEmail (emailAddress) { - let sQtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]' - let sDtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]' - let sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+' - let sQuotedPair = '\\x5c[\\x00-\\x7f]' - let sDomainLiteral = '\\x5b(' + sDtext + '|' + sQuotedPair + ')*\\x5d' - let sQuotedString = '\\x22(' + sQtext + '|' + sQuotedPair + ')*\\x22' - let sDomainRef = sAtom - let sSubDomain = '(' + sDomainRef + '|' + sDomainLiteral + ')' - let sWord = '(' + sAtom + '|' + sQuotedString + ')' - let sDomain = sSubDomain + '(\\x2e' + sSubDomain + ')*' - let sLocalPart = sWord + '(\\x2e' + sWord + ')*' - let sAddrSpec = sLocalPart + '\\x40' + sDomain // complete RFC822 email address spec - let sValidEmail = '^' + sAddrSpec + '$' // as whole string - - let reValidEmail = new RegExp(sValidEmail) - - return reValidEmail.test(emailAddress) -} - -const Wrapper = styled('div')(({ theme }) => ({ - marginTop: theme.spacing(1), - display: 'flex', - flexDirection: 'column', - alignItems: 'center', -})) - -const StyledAvatar = styled(Avatar)(({ theme }) => ({ - margin: theme.spacing(1), - backgroundColor: theme.palette.secondary.main, -})) - -const StyledForm = styled('form')(({ theme }) => ({ - width: '100%', - marginTop: theme.spacing(2), -})) - -const SubmitButton = styled(Button)(({ theme }) => ({ - margin: theme.spacing(3, 0, 2), - textTransform: 'none', - background: '#4A4EDD', - height: 50, - '&:hover': { - background: '#7F83FF', - }, -})) - -export default function ContactRecruiterForm (props) { - const [formData, setFormData] = useState({}) - const [formErrors, setFormErrors] = useState({}) - const { contact } = props - - const validate = (event) => { - const name = event.nativeEvent.target.name - const value = event.nativeEvent.target.value - const required = event.nativeEvent.target.hasAttribute('required') - if (required) { - if (name === 'email' && !checkEmail(value)) { - setFormErrors({ ...formErrors, email: 'invalid email' }) - } - else - if (value === '' || value.length < 3) { - setFormErrors({ ...formErrors, [name]: `invalid ${name}` }) - } - else { - setFormErrors({}) - } - } - } - - const onChange = (event) => { - const name = event.nativeEvent.target.name - const value = event.nativeEvent.target.value - setFormData({ ...formData, [name]: value }) - } - - const onSubmit = (event) => { - event.preventDefault() - if (Object.keys(formErrors).length === 0) { - props.contactRecruiters(formData) - } - } - - const onBlur = (event) => { - validate(event) - } - - return ( - - - - - - - - Contact us - - - - - - - - - - - - - - - - Phone: - - - - - - - - - - - - - - - - - - { contact.completed ? ( - Contact us - ) : ( - - ) } - - - - - - ) -} diff --git a/frontend/src/components/areas/public/features/welcome/legacy/country-list.js b/frontend/src/components/areas/public/features/welcome/legacy/country-list.js deleted file mode 100644 index efea37421..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/country-list.js +++ /dev/null @@ -1,36 +0,0 @@ -import React, { Component } from 'react' - -// note that you can also export the source data via CountryRegionData. It's in a deliberately concise format to -// keep file size down -import { CountryDropdown } from 'react-country-region-selector' - -export default class CountryList extends Component { - constructor (props) { - super(props) - this.state = { country: 'Select Country' } - } - - selectCountry (val) { - this.setState({ country: val }) - } - - render () { - const { country } = this.state - return ( -
- this.selectCountry(val) } /> -
- ) - } -} diff --git a/frontend/src/components/areas/public/features/welcome/legacy/home.js b/frontend/src/components/areas/public/features/welcome/legacy/home.js deleted file mode 100644 index 7c507b3c7..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/home.js +++ /dev/null @@ -1,232 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { Grid, Typography, Divider, List, ListItem, ListItemText, ListItemIcon, Button, Container } from '@mui/material' -import { styled } from '@mui/material/styles' - -import { - Work, - Archive, - CardMembership, - BugReport -} from '@mui/icons-material' - -import { injectIntl, FormattedMessage } from 'react-intl' - -import TopBarContainer from '../../../../../../containers/topbar' -import Bottom from 'design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout' -import messages from './messages' -// removed withStyles/theme styles usage - -import freelancerImage from 'images/collections/collection-flat-build.svg' -import citySoftware from 'images/collections/collection-flat-background.svg' -import deal from 'images/collections/collection-flat-works.svg' - -import { - MainTitle, - ResponsiveImage, - Section, - HeroSection, - HeroTitle, - HeroContent, - HeroActions -} from '../components/CommonStyles' - -// legacy styles removed - -class Home extends Component { - constructor (props) { - super(props) - - this.state = { - value: 0 - } - } - - render () { - const { } = this.props - - return ( -
- -
- - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - - -
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
- - - - - -
- -
- ) - } -} - -Home.propTypes = {} - -export default injectIntl(Home) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/how-it-works-company.js b/frontend/src/components/areas/public/features/welcome/legacy/how-it-works-company.js deleted file mode 100644 index ae79c7fa7..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/how-it-works-company.js +++ /dev/null @@ -1,138 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Work, - AccountBalanceWallet, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -class HowItWorksCompany extends Component { - constructor (props) { - super(props) - this.state = { - open: false - } - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - } - - componentDidMount () { - - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - render () { - const { classes } = this.props - - return ( - - - - { (msg) => ( - - ) } - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- ) - } -} - -HowItWorksCompany.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(HowItWorksCompany) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/how-it-works-people.js b/frontend/src/components/areas/public/features/welcome/legacy/how-it-works-people.js deleted file mode 100644 index 4aab179b3..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/how-it-works-people.js +++ /dev/null @@ -1,141 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Work, - AccountBalanceWallet, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -class HowItWorksPeople extends Component { - constructor (props) { - super(props) - this.state = { - open: false - } - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - render () { - const { classes } = this.props - - return ( - - - - { (msg) => ( - - ) } - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- ) - } -} - -HowItWorksPeople.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(HowItWorksPeople) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/landing-page.js b/frontend/src/components/areas/public/features/welcome/legacy/landing-page.js deleted file mode 100644 index 1ae176c44..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/landing-page.js +++ /dev/null @@ -1,406 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { FormattedMessage } from 'react-intl' -import { - Button, - AppBar, - Toolbar, - Grid, - Typography, - Link -} from '@mui/material' -import peopleImage from 'images/landingPage_People.png' -import logoGrey from 'images/logo-complete-gray.png' -import screenImage from 'images/gitpay-explore-task-screenshot.png' -import profileImage from 'images/avatar-alexandre.png' -import Bottom from 'design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout' -import Clientlist from './clientlist' -import TeamCard from 'design-library/molecules/cards/team-card/team-card' -import ContactRecruiterFormContainer from '../../../../../../containers/contact-recruiter-form' - -import deal from 'images/deal.png' - -import { - MainTitle, - MainList, - ResponsiveImage, - Section -} from '../components/CommonStyles' - -// Landing Page for GitPay -// Total hours worked on this: ~12hours -// Still need to add in functionality for buttons -// Export Styles to separate file to clean up code but left here for you to see for now - -import headhunterTeamMember1 from 'images/teams/headhunter-team-member1.png' - -const recruiterTeam = [ - { - name: 'Alexandre Magno', - description: 'Founder of Gitpay, and senior software engineer, sharing and helping developers to face the challenges of technical recruitment.', - image: headhunterTeamMember1, - linkedinUrl: 'https://www.linkedin.com/in/alexandremagnoteleszimerer/' - } -] - -const styles = (theme) => ({ - signText: { - fontWeight: 400, - marginTop: 0, - marginBottom: 3, - fontSize: '1.25em', - [theme.breakpoints.down('sm')]: { - fontSize: '1em', - }, - }, - buttonSignin: { - textTransform: 'none', - width: 120, - borderRadius: 25, - marginRight: 20, - '&:hover': { - color: 'white', - background: '#7F83FF', - }, - [theme.breakpoints.down('sm')]: { - width: 90, - }, - }, - buttonSignup: { - borderRadius: 25, - width: 130, - background: '#7F83FF', - color: 'white', - textTransform: 'none', - '&:hover': { - background: '#4A4EDD', - }, - [theme.breakpoints.down('sm')]: { - width: 90, - }, - }, - buttonHire: { - textTransform: 'none', - background: '#4A4EDD', - height: 50, - '&:hover': { - background: '#7F83FF', - }, - }, - buttonHireSmall: { - textTransform: 'none', - background: '#4A4EDD', - '&:hover': { - background: '#7F83FF', - }, - }, - buttonWork: { - border: '2px solid', - textTransform: 'none', - color: '#4A4EDD', - borderColor: '#4A4EDD', - marginRight: 20, - width: 150, - height: 50, - '&:hover': { - background: '#7F83FF', - border: '2px solid', - color: 'white', - }, - [theme.breakpoints.down('sm')]: { - marginRight: 0, - }, - }, - root: { - flexGrow: 1, - marginLeft: 50, - marginRight: 70, - marginTop: 50, - fontFamily: 'Arial', - fontWeight: '300', - color: '#2F2D2D', - lineHeight: '1.5em', - [theme.breakpoints.down('sm')]: { - display: 'flex', - margin: 'auto', - }, - }, - grow: { - flexGrow: 1, - }, - logoImage: { - width: 170, - [theme.breakpoints.down('sm')]: { - width: 120, - }, - }, - topBarContainer: { - marginTop: 40, - marginLeft: 70, - marginRight: 70, - }, - textContainer: { - marginTop: 60, - marginLeft: 30, - [theme.breakpoints.down('sm')]: { - marginLeft: 10, - marginRight: 10 - }, - }, - textSize: { - fontSize: '1.5em', - marginTop: 0, - marginBottom: 0, - }, - center: { - textAlign: 'center', - }, - justify: { - textAlign: 'justify', - }, - bottomImage: { - backgroundRepeat: 'no-repeat', - position: 'absolute', - width: '100vw', - [theme.breakpoints.down('sm')]: { - bottom: 0, - } - }, - header: { - fontSize: '2.5em', - fontWeight: 200, - marginTop: 70, - marginBottom: 36, - [theme.breakpoints.down('sm')]: { - lineHeight: 1.5, - fontSize: '1.3em', - } - }, - paragraph: { - fontSize: '1.2em', - lineHeight: 1.5, - [theme.breakpoints.down('sm')]: { - lineHeight: 1.5, - fontSize: '1em', - margin: '0 auto', - width: 270 - } - }, - margin: { - marginTop: 60, - marginBottom: 100, - marginLeft: 30, - [theme.breakpoints.down('sm')]: { - marginLeft: 0, - }, - }, -}) - -function LandingPage (props) { - const { classes } = props - const ref = React.createRef() - - const handleClick = (event) => { - event.preventDefault() - ref.current.scrollIntoView({ - behavior: 'smooth', - block: 'start', - }) - } - - return ( -
-
- - - - - - logo - -
- - - - - -

- -

-

-
- - - - - - -
- - - - - - -
- - - - - - - - - - - -
- -
-
-
- - - -
-
-
- - - - - - - - - - - -
- -
-
-
- - - -
-
-
- - - - - - - - - - - -
- -
-
-
- - - -
-
-
- - - - - -
-
-
- - - - - -
-
- -
- ) -} - -LandingPage.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default LandingPage diff --git a/frontend/src/components/areas/public/features/welcome/legacy/messages.js b/frontend/src/components/areas/public/features/welcome/legacy/messages.js deleted file mode 100644 index 4cb5bf6ee..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/messages.js +++ /dev/null @@ -1,292 +0,0 @@ -import { defineMessages } from 'react-intl' - -export default defineMessages({ - welcomeFreelancersItemOnePrimary: { - id: 'welcome.main.item.one.primary', - defaultMessage: 'Get paid by contributing with Open Source' - }, - welcomeFreelancersItemOneSecondary: { - id: 'welcome.main.item.one.secondary', - defaultMessage: 'Contribute with Open Source projects and receive rewards in bounties' - }, - welcomeFreelancersItemTwoPrimary: { - id: 'welcome.main.item.two.primary', - defaultMessage: 'Work with on-demand projects as a freelancer using a development workflow' - }, - welcomeFreelancersItemTwoSecondary: { - id: 'welcome.main.item.two.secondary', - defaultMessage: 'We use a Git Workflow to facilitate the process of delivery tasks on demand' - }, - welcomeFreelancersItemThreePrimary: { - id: 'welcome.main.item.three.primary', - defaultMessage: 'Contribute with projects, get paid, receive tailored feedbacks and get your code into production' - }, - welcomeFreelancersItemThreeSecondary: { - id: 'welcome.main.item.three.secondary', - defaultMessage: 'We use a very effective agile process to delivery tasks using Git, and we provide support to learn and improve your skills' - }, - welcomeCompaniesItemOnePrimary: { - id: 'welcome.companies.item.one.primary', - defaultMessage: 'Maintainers of Open Source projects can use Gitpay to outsource the development' - }, - welcomeCompaniesItemOneSecondary: { - id: 'welcome.companies.item.one.secondary', - defaultMessage: 'Import issues from Git, add bounties, then pay contributors when the related Pull Request is merged' - }, - welcomeCompaniesItemTwoPrimary: { - id: 'welcome.companies.item.two.primary', - defaultMessage: 'Organizations can use Gitpay to develop tasks on demand, using a development workflow' - }, - welcomeCompaniesItemTwoSecondary: { - id: 'welcome.companies.item.two.secondary', - defaultMessage: 'Pay for on-demand freelancer work using an integrated workflow and get issues from your project solved' - }, - welcomeCompaniesItemThreePrimary: { - id: 'welcome.companies.item.three.primary', - defaultMessage: 'Funding your Open Source project' - }, - welcomeCompaniesItemThreeSecondary: { - id: 'welcome.companies.item.three.secondary', - defaultMessage: 'You can crowdfunding your Open Source projects on Gitpay, and get funding by inviting sponsor to add bounties' - }, - welcomeHowToItemOnePrimary: { - id: 'welcome.howto.item.one.primary', - defaultMessage: 'Import an issue from a Git repository' - }, - welcomeHowToItemOneSecondary: { - id: 'welcome.howto.item.one.secondary', - defaultMessage: 'Import an issue to be solved, then you can set deadlines, add bounties and we will send to our community' - }, - welcomeHowToItemTwoPrimary: { - id: 'welcome.howto.item.two.primary', - defaultMessage: 'Contributors and freelancers can apply to solve your issue' - }, - welcomeHowToItemTwoSecondary: { - id: 'welcome.howto.item.two.secondary', - defaultMessage: 'The users can send offers and the ones who applied can be assigned to complete the work' - }, - welcomeHowToItemThreePrimary: { - id: 'welcome.howto.item.three.primary', - defaultMessage: 'When the solution is ready, you can review, and once approved, you can merge and send the payment to the peer' - }, - welcomeHowToItemThreeSecondary: { - id: 'welcome.howto.item.three.secondary', - defaultMessage: 'An easy way to have your work integrated with development tools approved by the development community' - }, - welcomeHowToItemFourPrimary: { - id: 'welcome.howto.item.four.primary', - defaultMessage: 'Your issue was solved, and the contributor received the payment' - }, - welcomeHowToItemFourSecondary: { - id: 'welcome.howto.item.four.secondary', - defaultMessage: 'We support payments with Credit Card or Paypal and the bounties are transfered directly to your bank account' - }, - consultingItemPrimary: { - id: 'welcome.how.item.primary', - defaultMessage: 'Create an account on Gitpay' - }, - consultingItemSecondary: { - id: 'welcome.how.item.secondary', - defaultMessage: 'When you create an account, you can setup payment methods to receive bounties, setup your preferences and explore tasks. You can receive issues funded according to your preferences' - }, - consultingItemTwoPrimary: { - id: 'welcome.how.item.two.primary', - defaultMessage: 'Solve issues' - }, - consultingItemTwoSecondary: { - id: 'welcome.how.item.two.secondary', - defaultMessage: 'You can apply to solve issues and receive the payment for a bounty, or even apply for learning purposes, to improve your skills' - }, - consultingItemThreePrimary: { - id: 'welcome.how.item.three.primary', - defaultMessage: 'Receive payments with direct transfer or Paypal' - }, - consultingItemThreeSecondary: { - id: 'welcome.how.item.three.secondary', - defaultMessage: 'Once your changes are merged into the code base and the issue was solved, you will receive the payment in your bank account' - }, - communityItemPrimary: { - id: 'welcome.community.item.primary', - defaultMessage: '8% fee to receive payments for the issues solved' - }, - communityItemSecondary: { - id: 'welcome.community.item.secondary', - defaultMessage: 'We accept direct transfer to your bank account registered on Gitpay or using your Paypal account' - }, - communityItemTwoPrimary: { - id: 'welcome.community.item.two.primary', - defaultMessage: 'A place for opportunities' - }, - communityItemTwoSecondary: { - id: 'welcome.community.item.two.secondary', - defaultMessage: 'You may become one of our top talents and there is chances that you can be hired by partner companies' - }, - communityItemThreePrimary: { - id: 'welcome.community.item.three.primary', - defaultMessage: 'A great workflow that helps you to focus in what matter' - }, - communityItemThreeSecondary: { - id: 'welcome.community.item.three.secondary', - defaultMessage: 'We follow git good practices to automate your delivery using git, and now you can work with tools you love and you will be supported with collaboration to solve issues' - }, - companiesHowItWorksItemPrimary: { - id: 'welcome.howitworks.companies.item.primary', - defaultMessage: 'Import git issues to Gitpay' - }, - companiesHowItWorksItemSecondary: { - id: 'welcome.howitworks.companies.item.secondary', - defaultMessage: 'Import issues from your Github or Bitbucket projects using git to be able to add bounties and manage fundings, and set deadlines and workflows for payments' - }, - companiesHowItWorksItemTwoPrimary: { - id: 'welcome.howitworks.companies.item.two.primary', - defaultMessage: 'Assign contributors to solve' - }, - companiesHowItWorksItemTwoSecondary: { - id: 'welcome.howitworks.companies.item.two.secondary', - defaultMessage: 'Contributors can apply for interest and make offers and you can approve their offers to solve your issues' - }, - companiesHowItWorksItemThreePrimary: { - id: 'welcome.howitworks.companies.item.three.primary', - defaultMessage: 'Receive a change proposal using Pull Requests' - }, - companiesHowItWorksItemThreeSecondary: { - id: 'welcome.howitworks.companies.item.three.secondary', - defaultMessage: 'The change request will be send directly to your approval, and once approved, the change is merged and the payment will be send to the peer' - }, - companiesItemPrimary: { - id: 'welcome.which.companies.item.primary', - defaultMessage: 'For any company' - }, - companiesItemSecondary: { - id: 'welcome.which.companies.item.secondary', - defaultMessage: 'The distributed colaboration helps company grows and provide a great solution to have the tasks solved using agile process and colaboration throught development' - }, - companiesItemTwoSecondary: { - id: 'welcome.which.companies.item.two.secondary', - defaultMessage: 'Companies will be able to use Open Source if they want to create colaborative tools that will help other companies and contribute with the OSS ecosystem' - }, - companiesItemThreePrimary: { - id: 'welcome.which.companies.item.three.primary', - defaultMessage: 'We validate your business integration process' - }, - companiesItemThreeSecondary: { - id: 'welcome.which.companies.item.three.secondary', - defaultMessage: 'We will help to fit in agile process to have your tasks concluded in an independent way and according to your business' - }, - companiesItemPrimary1: { - id: 'welcome.companies.item.primary', - defaultMessage: '8% for Open Source projects' - }, - companiesItemSecondary1: { - id: 'welcome.companies.item.secondary', - defaultMessage: '8% fee for Open Source Projects' - }, - companiesItemTwoPrimary1: { - id: 'welcome.companies.item.two.primary.alt', - defaultMessage: '18% for private projects' - }, - companiesItemTwoSecondary1: { - id: 'welcome.companies.item.two.secondary.alt', - defaultMessage: '18% fee for private projects' - }, - companiesItemThreePrimary1: { - id: 'welcome.companies.item.three.primary.alt', - defaultMessage: 'The fees are not refundable' - }, - companiesItemThreeSecondary1: { - id: 'welcome.companies.item.three.secondary.alt', - defaultMessage: 'You can refund your payment, or transfer to another issue, but the fees are not refundable' - }, - workflowItemPrimary: { - id: 'welcome.workflow.item.primary', - defaultMessage: 'Use of personal information' - }, - workflowItemSecondary: { - id: 'welcome.workflow.item.secondary', - defaultMessage: 'The company may use personal information for the following purposes: login and signup for Gitpay service, email notifications when enabled, and statistic data when authorized' - }, - workflowItemTwoPrimary: { - id: 'welcome.workflow.item.two.primary', - defaultMessage: 'Integration with third party' - }, - workflowItemTwoSecondary: { - id: 'welcome.workflow.item.two.secondary', - defaultMessage: 'We never provide access to your data to a third party without your previous consent' - }, - workflowItemThreePrimary: { - id: 'welcome.workflow.item.three.primary', - defaultMessage: 'Use of Cookies' - }, - workflowItemThreeSecondary: { - id: 'welcome.workflow.item.three.secondary', - defaultMessage: 'We use cookies to help to improve your experience with Gitpay, providing a custom experience according with your needs' - }, - termsItemOnePrimary: { - id: 'welcome.terms.item.one.primary', - defaultMessage: 'Terms' - }, - termsItemOneSecondary: { - id: 'welcome.terms.item.one.secondary', - defaultMessage: 'THIS IS A LEGALLY BINDING AGREEMENT between you and Work n Enjoy Inc., former company of Gitpay. By using gitpay.me website ("Site") or any of the Gitpay services and integrations ("Services"), you agree to all the terms and conditions of this Terms of Service ("Agreement"). If you are entering into this Agreement on behalf of a company or other legal entity, you represent that you have the authority to bind such entity to these terms and conditions, in which case the terms "you" or "your" shall refer to such entity. If you do not have such authority, or if you do not agree with these terms and conditions, you must not proceed with the registration process or use our Site or Service.' - }, - welcomeCollabItemOnePrimary: { - id: 'welcome.collab.item.one.primary', - defaultMessage: 'By developers, for developers' - }, - welcomeCollabItemOneSecondary: { - id: 'welcome.collab.item.one.secondary', - defaultMessage: 'We use tools like Git, and integrations with Github and Gitlab to automate the freelancer process' - }, - welcomeCollabItemTwoPrimary: { - id: 'welcome.collab.item.two.primary', - defaultMessage: 'We are fully Open Source' - }, - welcomeCollabItemTwoSecondary: { - id: 'welcome.collab.item.two.secondary', - defaultMessage: 'We are a open source project made by contributors, and we help our community of contributors to shift their careers to the next level' - }, - welcomeCollabItemThreePrimary: { - id: 'welcome.collab.item.three.primary', - defaultMessage: 'Collaborate from anywhere, empowering development communities' - }, - welcomeCollabItemThreeSecondary: { - id: 'welcome.collab.item.three.secondary', - defaultMessage: 'We use collaborative remote tools like Slack and discuss and review code on Github or Bitbucket, and we do payments for bounties and freelancer work worldwide' - }, - topMenu1: { - id: 'welcome.menu.item.one', - defaultMessage: 'Intro' - }, - topMenu2: { - id: 'welcome.menu.item.two', - defaultMessage: 'For contributors' - }, - topMenu3: { - id: 'welcome.menu.item.three', - defaultMessage: 'For organizations' - }, - topMenu4: { - id: 'welcome.menu.item.four', - defaultMessage: 'Community' - }, - topMenu5: { - id: 'welcome.menu.item.five', - defaultMessage: 'How it works' - }, - topMenu6: { - id: 'welcome.menu.item.six', - defaultMessage: 'Fees' - }, - topMenu7: { - id: 'welcome.menu.item.seven', - defaultMessage: 'Integrations' - }, - topMenu8: { - id: 'welcome.menu.item.eight', - defaultMessage: 'Get started' - }, - topMenu9: { - id: 'welcome.menu.item.nine', - defaultMessage: 'Who is using Gitpay' - } -}) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-company.js b/frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-company.js deleted file mode 100644 index bfbfa478f..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-company.js +++ /dev/null @@ -1,114 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -class TermsOfServiceCompany extends Component { - constructor (props) { - super(props) - this.state = { - open: false - } - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - } - - componentDidMount () { - - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - render () { - const { classes } = this.props - - return ( - - - - { (msg) => ( - - ) } - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - -
-
-
- ) - } -} - -TermsOfServiceCompany.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(TermsOfServiceCompany) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-people.js b/frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-people.js deleted file mode 100644 index 475900ec2..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/terms-of-service-people.js +++ /dev/null @@ -1,114 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -class TermsOfServicePeople extends Component { - constructor (props) { - super(props) - this.state = { - open: false - } - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - } - - componentDidMount () { - - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - render () { - const { classes } = this.props - - return ( - - - - { (msg) => ( - - ) } - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - -
-
-
- ) - } -} - -TermsOfServicePeople.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(TermsOfServicePeople) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/welcome.js b/frontend/src/components/areas/public/features/welcome/legacy/welcome.js deleted file mode 100644 index 5e0474aa0..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/welcome.js +++ /dev/null @@ -1,256 +0,0 @@ -import React, { useRef } from 'react' -import PropTypes from 'prop-types' -import { Grid, Typography, List, ListItem, ListItemText, ListItemIcon, Avatar, Container } from '@mui/material' -import { AccountBalanceWallet, Work, Apps, Assignment, GroupWork } from '@mui/icons-material' -import { injectIntl, FormattedMessage } from 'react-intl' -import TopBarContainer from '../../../../../../containers/topbar' -import Bottom from 'design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout' -import messages from './messages' -// removed withStyles/theme styles usage -import freelancerImage from 'images/collections/collection-flat-community.svg' -import companiesImage from 'images/collections/collection-flat-companies.svg' -import teamImage from 'images/welcome-teamwork.png' - -import { - MainTitle, - MainList, - ResponsiveImage, - Section -} from '../components/CommonStyles' - -// legacy styles removed - -const Welcome = (props) => { - const ref = useRef(null) - const [value, setValue] = React.useState(0) - - React.useEffect(() => { - // componentDidMount() equivalent - }, []) - - React.useEffect(() => { - // componentWillUnmount() equivalent - return () => { - // Clean up code - } - }, []) - - const { } = props - - return ( -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- ) -} - -Welcome.propTypes = {} - -export default injectIntl(Welcome) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/which-companies.js b/frontend/src/components/areas/public/features/welcome/legacy/which-companies.js deleted file mode 100644 index 83d69be56..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/which-companies.js +++ /dev/null @@ -1,134 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Work, - AccountBalanceWallet, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -class WhichCompanies extends Component { - constructor (props) { - super(props) - this.state = { - open: false - } - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - render () { - const { classes } = this.props - - return ( - - - - { (msg) => ( - - ) } - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- ) - } -} - -WhichCompanies.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(WhichCompanies) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/who-subscribes.js b/frontend/src/components/areas/public/features/welcome/legacy/who-subscribes.js deleted file mode 100644 index 6aca8d615..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/who-subscribes.js +++ /dev/null @@ -1,114 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -class WhoSubscribes extends Component { - constructor (props) { - super(props) - this.state = { - open: false - } - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - } - - componentDidMount () { - - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - render () { - const { classes } = this.props - - return ( - - - - { (msg) => ( - - ) } - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - -
-
-
- ) - } -} - -WhoSubscribes.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(WhoSubscribes) diff --git a/frontend/src/components/areas/public/features/welcome/legacy/workflow.js b/frontend/src/components/areas/public/features/welcome/legacy/workflow.js deleted file mode 100644 index dab55ecae..000000000 --- a/frontend/src/components/areas/public/features/welcome/legacy/workflow.js +++ /dev/null @@ -1,138 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import { injectIntl, FormattedMessage } from 'react-intl' - -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Dialog, - AppBar, - Toolbar, - IconButton, - Typography, - Avatar, -} from '@mui/material' -import { - Apps, - Work, - AccountBalanceWallet, - Close -} from '@mui/icons-material' - -import Transition from 'design-library/atoms/transitions/transition' -import messages from './messages' - -import { InfoList, MainTitle } from '../components/CommonStyles' - -class Workflow extends Component { - constructor (props) { - super(props) - this.state = { - open: false - } - this.handleClickOpen = this.handleClickOpen.bind(this) - this.handleClose = this.handleClose.bind(this) - } - - componentDidMount () { - - } - - handleClickOpen () { - this.setState({ open: true }) - } - - handleClose () { - this.setState({ open: false }) - } - - render () { - const { classes } = this.props - - return ( - - - - { (msg) => ( - - ) } - - - - - - - - - - - - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- ) - } -} - -Workflow.propTypes = { - classes: PropTypes.object.isRequired, -} - -export default injectIntl(Workflow) diff --git a/frontend/src/components/design-library/molecules/content/cookie-policy/cookie-policy.tsx b/frontend/src/components/design-library/molecules/content/cookie-policy/cookie-policy.tsx new file mode 100644 index 000000000..3a08e8ad6 --- /dev/null +++ b/frontend/src/components/design-library/molecules/content/cookie-policy/cookie-policy.tsx @@ -0,0 +1,81 @@ +import React from "react"; +import { Typography } from "@mui/material"; +import { FormattedMessage } from "react-intl"; + + +const CookiePolicy = ({ extraStyles = true }) => { + + const content = ` + {br} + Introduction + {br} +Welcome to Gitpay! This Cookie Policy explains how we use cookies, similar tracking technologies, and your choices regarding such technologies when you visit our website. +{br} +{br} +What are cookies? +Cookies are small text files that are stored on your device (computer, tablet, or mobile) when you visit a website. They enable the website to remember your actions and preferences (such as login details, language, font size, and other display preferences) over a period of time, so you don't have to keep re-entering them whenever you come back to the site or browse from one page to another. +{br} +{br} +Types of cookies we use +We use the following types of cookies on Gitpay: +{br} +{br} +a) Essential cookies: +These cookies are necessary for the operation of our website and enable you to navigate the site and use its features. Without these cookies, certain functionalities may be unavailable. +{br} +{br} +b) Analytical cookies: +Analytical cookies help us understand how visitors interact with our website by collecting information anonymously. This data helps us analyze and improve the performance and usability of our website. +{br} +{br} +c) Functional cookies: +Functional cookies allow us to remember your preferences and provide enhanced functionality and personalization. These cookies may be set by us or by third-party providers whose services we have added to our pages. +{br} +{br} +d) Advertising cookies: +Advertising cookies are used to deliver relevant advertisements to you. They track your browsing habits and help us display personalized ads based on your interests. These cookies may be set by us or by third-party advertising networks. +{br}{br} + +Third-party cookies +We may also use cookies from third-party services, such as Google Analytics, to track and analyze website usage. These third-party cookies are subject to the respective third parties' privacy policies. +{br}{br} +Cookie management{br} +You can manage and control cookies in various ways. You can set your browser to refuse all or some cookies, or to alert you when websites set or access cookies. Please note that if you disable or refuse cookies, some parts of our website may become inaccessible or not function properly. +{br}{br} +To manage your cookie preferences, you can modify the settings in your browser. Each browser has different procedures for managing cookies, so please refer to the instructions provided by your browser. +{br}{br} +Updates to this Cookie Policy{br} +We may update this Cookie Policy from time to time to reflect changes in our practices or legal requirements. We will post any revised version on this page with an updated effective date. +{br}{br} +Contact us +{br}{br} +If you have any questions or concerns about this Cookie Policy or our use of cookies on Gitpay, please contact us at [insert contact information]. +{br} +Please note that this Cookie Policy should be read in conjunction with our Privacy Policy, which provides further information on how we collect, use, and disclose your personal data. + ` + + return ( + <> +
+
+ + + + + + +
+ + + +
+ + }} /> + +
+
+ + ) +} + +export default CookiePolicy; diff --git a/frontend/src/components/areas/public/features/welcome/components/CommonStyles.js b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/CommonStyles.js similarity index 95% rename from frontend/src/components/areas/public/features/welcome/components/CommonStyles.js rename to frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/CommonStyles.js index 4afad332a..2eeb1746f 100644 --- a/frontend/src/components/areas/public/features/welcome/components/CommonStyles.js +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/CommonStyles.js @@ -1,6 +1,6 @@ import styled, { css } from 'styled-components' -import media from '../../../../../../styleguide/media' +import media from '../../../../../styleguide/media' export const MainTitle = styled.div` text-align: center; @@ -55,7 +55,7 @@ export const ShadowImage = styled.img` export const InfoList = styled.div` text-align: left; - margin-left: 10%; + margin-left: 6%; ${media.phone` margin-left: 0; diff --git a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts index 7e15e7219..5fea6cb06 100644 --- a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts @@ -1,104 +1,12 @@ import { styled } from '@mui/material/styles' -import AppBar from '@mui/material/AppBar' +import MuiAppBar from '@mui/material/AppBar' +import { Typography } from '@mui/material' -export const AppBarStyled = styled(AppBar)(({ theme }) => ({ - position: 'relative' +export const AppBarHeader = styled(Typography)(({ theme }) => ({ + color: theme.palette.primary.main })) -export const AppBarHeader = styled('div')(({ theme }) => ({ - marginLeft: theme.spacing(2), - flex: 1 -})) - -export const MainTitle = styled('div')<{ - left?: boolean; - center?: boolean; -}>(({ theme, left, center }) => ({ - textAlign: 'center', - display: 'block', - paddingBottom: 10, - borderBottom: '5px solid black', - width: '60%', - marginTop: 20, - marginLeft: 'auto', - marginBottom: 20, - marginRight: 'auto', - ...(left ? { marginRight: '18%' } : {}), - ...(center ? { marginRight: '5%', width: '70%' } : {}), - [theme.breakpoints.down('sm')]: { - width: '60%', - margin: '20px auto', - ...(left ? { marginLeft: 'auto' } : {}) - } -})) - -export const MainList = styled('div')(({ theme }) => ({ - textAlign: 'left', - [theme.breakpoints.down('sm')]: { - marginLeft: 0 - } -})) - -export const ResponsiveImage = styled('img')(({ theme }) => ({ - [theme.breakpoints.down('sm')]: { - width: '100%' - } -})) - -export const ShadowImage = styled('img')(({ theme }) => ({ - boxShadow: '1px 1px 3px 2px #ccc', - [theme.breakpoints.down('sm')]: { - maxWidth: '100%' - } -})) - -export const InfoList = styled('div')(({ theme }) => ({ - textAlign: 'left', - marginLeft: '10%', - [theme.breakpoints.down('sm')]: { - marginLeft: 0 - } -})) - -export const MainBanner = styled('div')(({ theme }) => ({ - boxSizing: 'border-box', - marginBottom: '1rem', - backgroundColor: 'black', - backgroundSize: 'cover', - [theme.breakpoints.down('sm')]: { - background: 'none', - backgroundColor: 'black' - } -})) - -export const Section = styled('div')<{ - alternative?: boolean -}>(({ theme, alternative }) => ({ - textAlign: 'center', - padding: '1rem', - ...(alternative ? { backgroundColor: '#f1f0ea' } : {}) -})) - -export const HeroTitle = styled('div')({}) - -export const HeroSection = styled('div')({ - marginTop: 20, - marginBottom: 20 -}) - -export const HeroContent = styled('div')({ - marginTop: 28, - marginBottom: 20 -}) - -export const HeroActions = styled('div')({ - display: 'flex', - justifyContent: 'flex-start', - alignItems: 'center', - padding: 10 -}) - -export const HeaderTypography = styled('div')({ - display: 'block', +export const AppBar = styled(MuiAppBar)({ + height: '100%', width: '100%' -}) +}) \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx index 3025ae66d..ac038590a 100644 --- a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx @@ -1,63 +1,49 @@ import React from 'react' import { - ListItemButton, - Typography, Dialog, Toolbar, IconButton, - Slide, - SlideProps } from '@mui/material' import { - Close + Close, } from '@mui/icons-material' -import { InfoList, AppBarStyled, AppBarHeader, HeaderTypography } from './bottom-section-dialog.styles' +import { InfoList } from './CommonStyles' +import { AppBar as AppBarStyles, AppBarHeader } from './bottom-section-dialog.styles' const BottomSectionDialog = ({ - Transition = React.forwardRef((props, ref) => ( - - )), - header, + open, + onClose, title, - subtitle, - content + content, }) => { - const [ open, setOpen ] = React.useState(false) - return ( - - setOpen(!open) } component={HeaderTypography as any}> - {header} - - setOpen(false) } - > - - - setOpen(false) } - aria-label="Close" - > - - - - {title} - - - - {content} - - - - + + + + + + + + {title} + + + + {content} + + + ) } diff --git a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx new file mode 100644 index 000000000..b9dd48b7a --- /dev/null +++ b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx @@ -0,0 +1,24 @@ +import type { Meta, StoryObj } from '@storybook/react' +import VerticalMenulList from './vertical-menu-list' + +const meta: Meta = { + title: 'Design Library/Molecules/Lists/VerticalMenuList', + component: VerticalMenulList, + parameters: { + layout: 'centered', + }, +} +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + title: 'Menu', + items: [ + { label: 'Dashboard', onClick: () => alert('Dashboard clicked') }, + { label: 'Settings', onClick: () => alert('Settings clicked') }, + { label: 'Logout', onClick: () => alert('Logout clicked') }, + ], + }, +} diff --git a/frontend/src/components/areas/public/features/welcome/legacy/github-app.js b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts similarity index 100% rename from frontend/src/components/areas/public/features/welcome/legacy/github-app.js rename to frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts diff --git a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx new file mode 100644 index 000000000..5239f09d2 --- /dev/null +++ b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx @@ -0,0 +1,54 @@ +import { List, ListItemButton, Typography } from '@mui/material' +import BottomSectionDialog from 'design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog' +import React from 'react' + +type VerticalMenuListProps = { + type?: 'link' | 'dialog' + title: string | React.ReactNode + items: { + label: string; + onClick?: () => void + component?: React.ReactNode + }[] +} + +const VerticalMenuList = ({ + type = 'link', + title, + items +}: VerticalMenuListProps) => { + + const [ open, setOpen ] = React.useState(-1) + + return ( + <> + + {title} + + + {items.map((item, index) => ( + + setOpen(index) }} + > + {item.label} + + + ))} + + { type === 'dialog' && open >= 0 && items[open].component && + setOpen(-1) } + /> + } + + ) +} + +export default VerticalMenuList \ No newline at end of file diff --git a/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx b/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx index d77159235..2258ad021 100644 --- a/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx +++ b/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx @@ -1,153 +1,77 @@ import React from 'react' import { FormattedMessage } from 'react-intl' +import { useHistory } from 'react-router-dom' import { Grid, Typography, - List, - ListItemButton } from '@mui/material' import SubscribeForm from '../../../forms/subscribe-forms/subscribe-form/subscribe-form' import StatsBar from '../../../../molecules/sections/stats-bar/stats-bar' import SlackCard from './SlackCard' import GithubCard from './GithubCard' +import VerticalMenuList from '../../../../molecules/lists/vertical-menu-list/vertical-menu-list' import { Container, BaseFooter, SubscribeFromWrapper, SecBlock, SpacedDivider, LogoImg } from './bottom-bar-layout.styles' - -import BottomSectionDialog from '../../../../../areas/public/features/welcome/components/BottomSectionDialog' -import PrivacyPolicy from '../../../../../areas/private/components/session/privacy-policy' -import TermsOfService from '../../../../../areas/private/components/session/terms-of-service' -import CookiePolicy from '../../../../../areas/private/components/session/cookie-policy' +import PrivacyPolicy from '../../../../molecules/content/privacy-policy/privacy-policy' +import TermsOfService from '../../../../molecules/content/terms-of-service/terms-of-service' +import CookiePolicy from '../../../../molecules/content/cookie-policy/cookie-policy' import logoCompleteGray from 'images/logo-complete-gray.png' import logoWorknEnjoy from 'images/worknenjoy-logo.png' const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0 }, getInfo }) => { + const history = useHistory() const { tasks, bounties, users } = info + const mainMenuItems = [ + { label: 'About us', onClick: () => history.push('/welcome') }, + { label: 'Pricing', onClick: () => history.push('/pricing') }, + { label: 'Team', onClick: () => history.push('/team') }, + { label: 'Documentation', onClick: () => window.open('https://docs.gitpay.me/en') }, + { label: 'Explore', onClick: () => history.push('/explore/issues') } + ] + + const legalMenuItems = [ + { + label: 'Privacy policy', + component: + }, + { + label: 'Terms of Service', + component: + }, + { + label: 'Cookie Policy', + component: + } + ] + return ( - - - - - - - - window.location.assign('/#/welcome')} - > - - - - - window.location.assign('/#/pricing')} - > - - - - - window.location.assign('/#/team')} - > - - - - - window.open('https://docs.gitpay.me/en')} - > - - - - - window.location.assign('/#/tasks/open')} - > - - - - + } + items={mainMenuItems} + /> - - + - - - - - } - /> - - } - /> - - } - /> - + } + items={legalMenuItems} + /> diff --git a/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx index 62d75c623..d256621d5 100644 --- a/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx @@ -3,10 +3,8 @@ import React from 'react' import { Button, Card, CardActions, CardContent, CardHeader, Grid, Typography } from '@mui/material' import { FormattedMessage } from 'react-intl' -import { - MainTitle -} from '../../../../areas/public/features/welcome/components/CommonStyles' import { Layout, HeroContent, CardPricing } from './pricing-public-page.styles' +import MainTitle from 'design-library/atoms/typography/main-title/main-title' interface Tier { title: string @@ -71,14 +69,10 @@ function PricingPublicPage() { { /* Hero unit */ } - - - - - - - - + } + subtitle={} + /> { /* End hero unit */ } From 36c3b95ed1c183fcf6ad7413133d704d7a4fcfd1 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Sat, 8 Nov 2025 13:20:42 +0100 Subject: [PATCH 13/19] bottom bar and pricing page adjustments --- .../privacy-policy/privacy-policy.stories.tsx | 12 -- .../terms-of-service.stories.tsx | 14 -- .../terms/base-terms/base-terms.stories.tsx | 67 +++++++++ .../terms/base-terms/base-terms.styles.ts | 44 ++++++ .../content/terms/base-terms/base-terms.tsx | 70 +++++++++ .../cookie-policy/cookie-policy.stories.tsx | 24 +++ .../cookie-policy/cookie-policy.tsx | 27 +--- .../privacy-policy/privacy-policy.stories.tsx | 32 ++++ .../privacy-policy/privacy-policy.tsx | 48 ++---- .../terms-of-service.stories.tsx | 35 +++++ .../terms-of-service/terms-of-service.tsx | 43 ++---- .../bottom-section-dialog/CommonStyles.js | 2 +- .../bottom-section-dialog.styles.ts | 10 +- .../bottom-section-dialog.tsx | 47 +++--- .../dialogs/privacy-dialog/privacy-dialog.tsx | 2 +- .../dialogs/terms-dialog/terms-dialog.tsx | 2 +- .../vertical-menu-list.stories.tsx | 13 ++ .../vertical-menu-list.styles.ts | 16 ++ .../vertical-menu-list/vertical-menu-list.tsx | 24 +-- .../bottom-bar-layout/bottom-bar-layout.tsx | 142 ++---------------- .../pricing-public-page.tsx | 102 +++++++------ 21 files changed, 453 insertions(+), 323 deletions(-) delete mode 100644 frontend/src/components/design-library/molecules/content/privacy-policy/privacy-policy.stories.tsx delete mode 100644 frontend/src/components/design-library/molecules/content/terms-of-service/terms-of-service.stories.tsx create mode 100644 frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx create mode 100644 frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts create mode 100644 frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.tsx create mode 100644 frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx rename frontend/src/components/design-library/molecules/content/{ => terms}/cookie-policy/cookie-policy.tsx (75%) create mode 100644 frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx rename frontend/src/components/design-library/molecules/content/{ => terms}/privacy-policy/privacy-policy.tsx (62%) create mode 100644 frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx rename frontend/src/components/design-library/molecules/content/{ => terms}/terms-of-service/terms-of-service.tsx (62%) diff --git a/frontend/src/components/design-library/molecules/content/privacy-policy/privacy-policy.stories.tsx b/frontend/src/components/design-library/molecules/content/privacy-policy/privacy-policy.stories.tsx deleted file mode 100644 index 854518728..000000000 --- a/frontend/src/components/design-library/molecules/content/privacy-policy/privacy-policy.stories.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import PrivacyPolicy from './privacy-policy'; - -export default { - title: 'Design Library/Molecules/Content/PrivacyPolicy', - component: PrivacyPolicy -}; - -const Template = (args) => ; - -export const Default = Template.bind({}); -Default.args = {}; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/content/terms-of-service/terms-of-service.stories.tsx b/frontend/src/components/design-library/molecules/content/terms-of-service/terms-of-service.stories.tsx deleted file mode 100644 index 4fd2a25c9..000000000 --- a/frontend/src/components/design-library/molecules/content/terms-of-service/terms-of-service.stories.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import TermsOfService from './terms-of-service'; - -export default { - title: 'Design Library/Molecules/Content/TermsOfService', - component: TermsOfService -}; - -const Template = (args) => ; - -export const Default = Template.bind({}); -Default.args = { - // Add default props here if any -}; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx new file mode 100644 index 000000000..990d472dc --- /dev/null +++ b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx @@ -0,0 +1,67 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { action } from "@storybook/addon-actions"; +import BaseTerms from "./base-terms"; + +const meta: Meta = { + title: "Design Library/Molecules/Content/Terms/BaseTerms", + component: BaseTerms, + parameters: { + layout: "centered", + }, +}; +export default meta; + +type Story = StoryObj; + +const baseArgs = { + title: "Terms of Service", + subtitle: "Please read these terms carefully before using our service.", + updated: "Last updated: Jan 1, 2025", + content: + "By accessing or using the service you agree to be bound by these Terms. If you disagree with any part of the terms then you may not access the service.", + // extraStyles defaults to true in the component +}; + +export const Default: Story = { + args: { + ...baseArgs, + }, +}; + +export const WithActions: Story = { + args: { + ...baseArgs, + onArrowBack: action("onArrowBack"), + onAgreeTerms: action("onAgreeTerms"), + }, +}; + +export const NoHeader: Story = { + args: { + ...baseArgs, + noHeader: true, + }, +}; + +export const WithoutExtraStyles: Story = { + args: { + ...baseArgs, + extraStyles: false, + }, +}; + +export const LongContent: Story = { + args: { + ...baseArgs, + content: + "These terms apply to all visitors, users and others who access or use the service. " + + "You are responsible for safeguarding the password that you use to access the service. " + + "You agree not to disclose your password to any third party. " + + "Accounts may be terminated for violations of these terms. " + + "We may terminate or suspend access to our service immediately, without prior notice or liability, " + + "for any reason whatsoever, including without limitation if you breach the terms. " + + "The service and its original content, features and functionality are and will remain the exclusive " + + "property of the company and its licensors. " + + "We reserve the right, at our sole discretion, to modify or replace these terms at any time.", + }, +}; diff --git a/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts new file mode 100644 index 000000000..c50d88889 --- /dev/null +++ b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts @@ -0,0 +1,44 @@ +import { styled } from "@mui/material/styles"; +import { Paper, Button } from "@mui/material"; + +type TermsContainerProps = { + extraStyles?: boolean; +}; + +export const TermsContainer = styled("div")(({ extraStyles }) => ({ + ...(extraStyles + ? { + padding: 20, + textAlign: "left", + position: "absolute", + top: 0, + left: 0, + width: "100%", + background: "white", + } + : {}), +})); + +export const Header = styled("div")({ + marginBottom: 10, +}); + +export const ContentArea = styled("div")({ + overflow: "scroll", + height: "calc(100vh - 200px)", +}); + +export const ActionsBar = styled(Paper)({ + position: "absolute", + bottom: 20, + left: 0, + height: 80, + width: "100%", + background: "white", +}); + +export const ActionButton = styled(Button)({ + float: "right", + marginRight: 20, + marginTop: 20, +}); diff --git a/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.tsx b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.tsx new file mode 100644 index 000000000..de6c0eeb6 --- /dev/null +++ b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.tsx @@ -0,0 +1,70 @@ +import React from "react"; +import { Typography } from "@mui/material"; +import { ArrowBack } from "@mui/icons-material" +import { FormattedMessage } from "react-intl"; +import { TermsContainer, Header, ContentArea, ActionsBar, ActionButton } from "./base-terms.styles"; + +type BaseTermsProps = { + title: React.ReactNode | string; + subtitle: React.ReactNode | string; + updated: React.ReactNode | string; + content: React.ReactNode | string; + onArrowBack?: () => void; + onAgreeTerms?: () => void; + noHeader?: boolean; + extraStyles?: boolean; +}; + + +const BaseTerms = ({ + title, + subtitle, + updated, + content, + onArrowBack, + onAgreeTerms, + noHeader, + extraStyles = true +}:BaseTermsProps) => { + + return ( + <> + + { noHeader ? null : ( + <> +
+ { onArrowBack && ( + + + + )} + + {title} + + + {updated} + +
+ + {subtitle} + + + )} + + + {content} + + + { onAgreeTerms && ( + + + + + + )} +
+ + ) +} + +export default BaseTerms; diff --git a/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx new file mode 100644 index 000000000..be0fca9c2 --- /dev/null +++ b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx @@ -0,0 +1,24 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import CookiePolicy from './cookie-policy'; + +const meta: Meta = { + title: 'Design Library/Molecules/Content/Terms/CookiePolicy', + component: CookiePolicy, + args: { + extraStyles: true, + }, + argTypes: { + extraStyles: { control: 'boolean' }, + }, +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { extraStyles: true }, +}; + +export const NoExtraStyles: Story = { + args: { extraStyles: false }, +}; diff --git a/frontend/src/components/design-library/molecules/content/cookie-policy/cookie-policy.tsx b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.tsx similarity index 75% rename from frontend/src/components/design-library/molecules/content/cookie-policy/cookie-policy.tsx rename to frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.tsx index 3a08e8ad6..0e182090e 100644 --- a/frontend/src/components/design-library/molecules/content/cookie-policy/cookie-policy.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { Typography } from "@mui/material"; import { FormattedMessage } from "react-intl"; +import BaseTerms from "../base-terms/base-terms"; const CookiePolicy = ({ extraStyles = true }) => { @@ -56,24 +56,13 @@ Please note that this Cookie Policy should be read in conjunction with our Priva return ( <> -
-
- - - - - - -
- - - -
- - }} /> - -
-
+ } + subtitle={} + updated={} + content={ }} />} + extraStyles={extraStyles} + /> ) } diff --git a/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx new file mode 100644 index 000000000..fe1d72596 --- /dev/null +++ b/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import PrivacyPolicy from './privacy-policy'; + +export default { + title: 'Design Library/Molecules/Content/Terms/PrivacyPolicy', + component: PrivacyPolicy +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = {}; + +export const WithoutHeader = Template.bind({}); +WithoutHeader.args = { + noHeader: true, +}; + +export const WithAgreeButton = Template.bind({}); +WithAgreeButton.args = { + onAgreeTerms: () => alert('Agreed to Privacy Policy'), +}; + +export const WithExtraStyles = Template.bind({}); +WithExtraStyles.args = { + extraStyles: true, +}; + +export const WithArrowBack = Template.bind({}); +WithArrowBack.args = { + onArrowBack: () => alert('Arrow back clicked'), +}; diff --git a/frontend/src/components/design-library/molecules/content/privacy-policy/privacy-policy.tsx b/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.tsx similarity index 62% rename from frontend/src/components/design-library/molecules/content/privacy-policy/privacy-policy.tsx rename to frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.tsx index 57135944c..ecc691c29 100644 --- a/frontend/src/components/design-library/molecules/content/privacy-policy/privacy-policy.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.tsx @@ -1,8 +1,6 @@ import React from "react"; -import { Typography } from "@mui/material"; -import { ArrowBack } from "@mui/icons-material" import { FormattedMessage } from "react-intl"; -import { Button, Paper } from "@mui/material"; +import BaseTerms from "../base-terms/base-terms"; type PrivacyPolicyProps = { onArrowBack?: () => void; @@ -47,40 +45,16 @@ If you have any questions or concerns about our privacy policy, please contact u return ( <> -
- { noHeader ? null : ( - <> -
- { onArrowBack && ( - - - - )} - - - - - - -
- - - - - )} -
- - }} /> - -
- { onAgreeTerms && ( - - - - )} -
+ } + subtitle={} + updated={} + content={ }} />} + extraStyles={extraStyles} + onArrowBack={onArrowBack} + onAgreeTerms={onAgreeTerms} + noHeader={noHeader} + /> ) } diff --git a/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx new file mode 100644 index 000000000..235a351a0 --- /dev/null +++ b/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import TermsOfService from './terms-of-service'; + +export default { + title: 'Design Library/Molecules/Content/Terms/TermsOfService', + component: TermsOfService +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + // Add default props here if any +}; + +export const WithArrowBack = Template.bind({}); +WithArrowBack.args = { + onArrowBack: () => alert('Arrow back clicked'), +}; + +export const WithAgreeButton = Template.bind({}); +WithAgreeButton.args = { + onAgreeTerms: () => alert('Agreed to Terms of Service'), +}; + +export const WithBothActions = Template.bind({}); +WithBothActions.args = { + onArrowBack: () => alert('Arrow back clicked'), + onAgreeTerms: () => alert('Agreed to Terms of Service'), +}; + +export const WithoutExtraStyles = Template.bind({}); +WithoutExtraStyles.args = { + extraStyles: false, +}; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/content/terms-of-service/terms-of-service.tsx b/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.tsx similarity index 62% rename from frontend/src/components/design-library/molecules/content/terms-of-service/terms-of-service.tsx rename to frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.tsx index 4c610e52d..452480094 100644 --- a/frontend/src/components/design-library/molecules/content/terms-of-service/terms-of-service.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.tsx @@ -1,8 +1,6 @@ import React from "react"; -import { Typography } from "@mui/material"; -import { ArrowBack } from "@mui/icons-material" import { FormattedMessage } from "react-intl"; -import { Button, Paper } from "@mui/material"; +import BaseTerms from "../base-terms/base-terms"; type TermsOfServiceProps = { onArrowBack?: () => void; @@ -50,36 +48,15 @@ By using our platform, you agree to these terms and conditions. If you do not ag return ( <> -
-
- { onArrowBack && ( - - - - )} - - - - - - -
- - - -
- - }} /> - -
- { onAgreeTerms && ( - - - - )} -
+ } + subtitle={} + updated={} + content={}} />} + extraStyles={extraStyles} + onArrowBack={onArrowBack} + onAgreeTerms={onAgreeTerms} + /> ) } diff --git a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/CommonStyles.js b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/CommonStyles.js index 2eeb1746f..1d1e47c2f 100644 --- a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/CommonStyles.js +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/CommonStyles.js @@ -55,7 +55,7 @@ export const ShadowImage = styled.img` export const InfoList = styled.div` text-align: left; - margin-left: 6%; + margin-left: 3%; ${media.phone` margin-left: 0; diff --git a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts index 5fea6cb06..e7d0f4649 100644 --- a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts @@ -1,9 +1,15 @@ import { styled } from '@mui/material/styles' import MuiAppBar from '@mui/material/AppBar' -import { Typography } from '@mui/material' +import { Toolbar, Typography } from '@mui/material' + +export const TopBarStyled = styled(Toolbar)(({ theme }) => ({ + borderBottom: `1px solid ${theme.palette.divider}`, + marginBottom: theme.spacing(2), +})) export const AppBarHeader = styled(Typography)(({ theme }) => ({ - color: theme.palette.primary.main + width: '100%', + color: theme.palette.common.white, })) export const AppBar = styled(MuiAppBar)({ diff --git a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx index ac038590a..a9ab16f31 100644 --- a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx @@ -1,8 +1,8 @@ import React from 'react' import { Dialog, - Toolbar, IconButton, + Slide, } from '@mui/material' import { @@ -10,7 +10,17 @@ import { } from '@mui/icons-material' import { InfoList } from './CommonStyles' -import { AppBar as AppBarStyles, AppBarHeader } from './bottom-section-dialog.styles' +import { AppBar as AppBarStyles, AppBarHeader, TopBarStyled } from './bottom-section-dialog.styles' +import { TransitionProps } from '@mui/material/transitions' + +const Transition = React.forwardRef(function Transition( + props: TransitionProps & { + children: React.ReactElement; + }, + ref: React.Ref, +) { + return ; +}); const BottomSectionDialog = ({ @@ -25,23 +35,26 @@ const BottomSectionDialog = ({ fullScreen open={ open } onClose={ onClose } + slots={{ + transition: Transition, + }} > - - - - - - {title} - - - - {content} - + + + + + + {title} + + + + {content} + ) diff --git a/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx index 882d5e5b4..6463187ea 100644 --- a/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Dialog, DialogContent, DialogContentText, DialogTitle } from "@mui/material"; -import PrivacyPolicy from "../../content/privacy-policy/privacy-policy"; +import PrivacyPolicy from "../../content/terms/privacy-policy/privacy-policy"; const PrivacyDialog = ({ open, diff --git a/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx index 9d6f4521f..c593cea1e 100644 --- a/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Dialog, DialogContent, DialogContentText, DialogTitle } from "@mui/material"; -import TermsOfService from "../../content/terms-of-service/terms-of-service"; +import TermsOfService from "../../content/terms/terms-of-service/terms-of-service"; const TermsDialog = ({ open, diff --git a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx index b9dd48b7a..b1f59eee0 100644 --- a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx +++ b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx @@ -1,3 +1,4 @@ +import React from 'react' import type { Meta, StoryObj } from '@storybook/react' import VerticalMenulList from './vertical-menu-list' @@ -22,3 +23,15 @@ export const Default: Story = { ], }, } + +export const DialogType: Story = { + args: { + type: 'dialog', + title: 'Legal', + items: [ + { label: 'Privacy Policy', component:
Privacy Policy Content
}, + { label: 'Terms of Service', component:
Terms of Service Content
}, + { label: 'Cookie Policy', component:
Cookie Policy Content
}, + ], + }, +} diff --git a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts index e69de29bb..fc4e69f43 100644 --- a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts +++ b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts @@ -0,0 +1,16 @@ +import { styled } from '@mui/material/styles' +import { List, ListItemButton, Typography } from '@mui/material' + +export const TitleStyled = styled(Typography)(({ theme }) => ({ + paddingLeft: theme.spacing(2), +})) + +export const ListStyled = styled(List)(({ theme }) => ({ + marginLeft: theme.spacing(0), + paddingLeft: theme.spacing(0), +})) + +export const ListItemButtonStyled = styled(ListItemButton)(({ theme }) => ({ + marginLeft: theme.spacing(0), + paddingLeft: theme.spacing(2), +})) \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx index 5239f09d2..bd8854a27 100644 --- a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx +++ b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.tsx @@ -1,12 +1,13 @@ -import { List, ListItemButton, Typography } from '@mui/material' -import BottomSectionDialog from 'design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog' import React from 'react' +import { Typography } from '@mui/material' +import { ListStyled, ListItemButtonStyled, TitleStyled } from './vertical-menu-list.styles' +import BottomSectionDialog from 'design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog' type VerticalMenuListProps = { type?: 'link' | 'dialog' - title: string | React.ReactNode + title: React.ReactNode | string items: { - label: string; + label: React.ReactNode | string onClick?: () => void component?: React.ReactNode }[] @@ -22,23 +23,22 @@ const VerticalMenuList = ({ return ( <> - - {title} - - + + {title} + + {items.map((item, index) => ( - + setOpen(index) }} > {item.label} - + ))} - + { type === 'dialog' && open >= 0 && items[open].component && { const history = useHistory() const { tasks, bounties, users } = info + const navigateTo = (path: string) => { + history.push(path) + window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) + } + const mainMenuItems = [ - { label: 'About us', onClick: () => history.push('/welcome') }, - { label: 'Pricing', onClick: () => history.push('/pricing') }, - { label: 'Team', onClick: () => history.push('/team') }, + { label: 'About us', onClick: () => navigateTo('/welcome') }, + { label: 'Pricing', onClick: () => navigateTo('/pricing') }, + { label: 'Team', onClick: () => navigateTo('/team') }, { label: 'Documentation', onClick: () => window.open('https://docs.gitpay.me/en') }, - { label: 'Explore', onClick: () => history.push('/explore/issues') } + { label: 'Explore', onClick: () => navigateTo('/explore/issues') } ] const legalMenuItems = [ { - label: 'Privacy policy', + label: , component: }, { - label: 'Terms of Service', - component: + label: , + component: }, { - label: 'Cookie Policy', + label: , component: } ] @@ -53,7 +58,6 @@ const Bottom = ({ info = { bounties: 0, tasks: 0, users: 0 }, getInfo }) => { -<<<<<<< HEAD { />} items={mainMenuItems} /> -======= - - - - - - - - window.location.assign('/#/welcome')} - > - - - - - window.location.assign('/#/pricing')} - > - - - - - window.location.assign('/#/team')} - > - - - - - window.open('https://docs.gitpay.me/en')} - > - - - - - window.location.assign('/#/tasks/open')} - > - - - - ->>>>>>> master { id="bottom.menu.legal" defaultMessage="Legal" /> -<<<<<<< HEAD } items={legalMenuItems} /> -======= - - - - - } - /> - - } - /> - - } - /> - ->>>>>>> master diff --git a/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx index d256621d5..b6f7ca03e 100644 --- a/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx @@ -5,6 +5,8 @@ import { Button, Card, CardActions, CardContent, CardHeader, Grid, Typography } import { FormattedMessage } from 'react-intl' import { Layout, HeroContent, CardPricing } from './pricing-public-page.styles' import MainTitle from 'design-library/atoms/typography/main-title/main-title' +import { HeroTitleStyled } from 'design-library/atoms/typography/hero-title/hero-title.styles' +import HeroTitle from 'design-library/atoms/typography/hero-title/hero-title' interface Tier { title: string @@ -67,63 +69,67 @@ function PricingPublicPage() { return ( - { /* Hero unit */ } - } - subtitle={} - /> + + + - { /* End hero unit */ } - - { tiersMaintainers.map(tier => ( - // Enterprise card is full width at sm breakpoint - - - theme.palette.primary.light }} - /> - - - - Fee { tier.price } - - - - - - { tier.description.map((line, i) => ( - - { line } - - )) } - - { tier.link && - - - - } - - - )) } + + + + } + subheader={} + sx={{ backgroundColor: theme => theme.palette.primary.light, textAlign: 'center' }} + /> + + + { tiersMaintainers.map(tier => ( + + + theme.palette.primary.light, textAlign: 'center' }} + /> + + + + Fee { tier.price } + + + + + + { tier.description.map((line, i) => ( + + { line } + + )) } + + { tier.link && + + + + } + + + )) } + + + + - + { tiersContributors.map(tier => ( - // Enterprise card is full width at sm breakpoint theme.palette.primary.light }} + sx={{ backgroundColor: theme => theme.palette.primary.light, textAlign: 'center' }} /> From 74f77947a96f071fa55d3b572af28cdba11155ed Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Sat, 8 Nov 2025 18:07:50 +0100 Subject: [PATCH 14/19] session pages into design library using a base template --- .../decorators/withPublicTemplate.tsx | 11 +- .../dialogs/privacy-dialog/privacy-dialog.tsx | 7 +- .../dialogs/terms-dialog/terms-dialog.tsx | 8 +- .../login-form-signup/login-form-signup.tsx | 270 +++++++++--------- 4 files changed, 151 insertions(+), 145 deletions(-) diff --git a/frontend/.storybook/decorators/withPublicTemplate.tsx b/frontend/.storybook/decorators/withPublicTemplate.tsx index 64959717d..65c6f45d5 100644 --- a/frontend/.storybook/decorators/withPublicTemplate.tsx +++ b/frontend/.storybook/decorators/withPublicTemplate.tsx @@ -1,5 +1,6 @@ import React from 'react'; import PublicBase from 'design-library/templates/base/public-base/public-base'; +import SignupSigninBase from 'design-library/templates/base/signup-signin-base/signup-signin-base'; import ExplorerPublicPage from 'design-library/pages/public-pages/explorer-public-page/explorer-public-page/explorer-public-page'; export const withPublicTemplate = (Story: any, context: any) => { @@ -27,4 +28,12 @@ export const withPublicExplorerTemplate = (Story: any, context: any) => { ) -}; \ No newline at end of file +}; + +export const withSignupSigninBaseTemplate = (Story: any, context: any) => { + return ( + + + + ) +}; diff --git a/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx index 6463187ea..75f4a5e71 100644 --- a/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/privacy-dialog/privacy-dialog.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Dialog, DialogContent, DialogContentText, DialogTitle } from "@mui/material"; +import { Dialog, DialogContent } from "@mui/material"; import PrivacyPolicy from "../../content/terms/privacy-policy/privacy-policy"; const PrivacyDialog = ({ @@ -9,11 +9,8 @@ const PrivacyDialog = ({ return ( - Privacy Policy - - - + ); diff --git a/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx index c593cea1e..b3fbd4595 100644 --- a/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx @@ -1,6 +1,7 @@ import React from "react"; -import { Dialog, DialogContent, DialogContentText, DialogTitle } from "@mui/material"; +import { Dialog, DialogContent, DialogTitle } from "@mui/material"; import TermsOfService from "../../content/terms/terms-of-service/terms-of-service"; +import { FormattedMessage } from "react-intl"; const TermsDialog = ({ open, @@ -9,11 +10,8 @@ const TermsDialog = ({ return ( - Terms and Conditions - - - + ); diff --git a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx index 06292b627..5675d56aa 100644 --- a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx +++ b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx @@ -289,148 +289,150 @@ const LoginFormSignup = ({ const { error, password, confirmPassword } = state return ( - - - - - - - - - - - - - : ''} - name="confirm_password" - onChange={handleChange('confirmPassword')} - onBlur={handleBlur} - onFocus={handleFocus} - fullWidth - type="password" - label="Confirm Password" - variant="outlined" - id="confirmPassword" - defaultValue={state.confirmPassword} - /> - - - - -
-
- {state.agreeTermsCheck - ? - : - } - - - - - - - - - - -
-
- {agreeTermsCheckError && -
- - - -
- } + <> + + + + + + + + + + - {process.env.NODE_ENV === 'production' && ( -
- setState({ ...state, captchaChecked })} + + : ''} + name="confirm_password" + onChange={handleChange('confirmPassword')} + onBlur={handleBlur} + onFocus={handleFocus} + fullWidth + type="password" + label="Confirm Password" + variant="outlined" + id="confirmPassword" + defaultValue={state.confirmPassword} /> + + + + +
+
+ {state.agreeTermsCheck + ? + : + } + + + + + + + + + + +
- )} - {error.captcha && -
- - {error.captcha} - -
- } -
-
- {noCancelButton ? null : ( - - - - )} - - - -
+ {agreeTermsCheckError && +
- + -
-
-
+ } + + {process.env.NODE_ENV === 'production' && ( +
+ setState({ ...state, captchaChecked })} + /> +
+ )} + {error.captcha && +
+ + {error.captcha} + +
+ } +
+
+ {noCancelButton ? null : ( + + + + )} + + + +
+ + + + +
+
+
+ - + ) } From b0171a49ad4c81ead91d8ccec21b3147f8711f1f Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Sat, 8 Nov 2025 21:44:35 +0100 Subject: [PATCH 15/19] moving account activation to design library and creating routing pages for session flows --- frontend/.storybook/main.js | 9 +- .../session/pages/account-activation-page.tsx | 11 ++ .../features/session/pages/session-page.tsx | 25 +++ .../cards/spot-card/spot-card.stories.tsx | 22 +++ .../cards/spot-card/spot-card.styles.ts | 18 ++ .../molecules/cards/spot-card/spot-card.tsx | 88 +++++++++ .../account-activation.stories.tsx | 0 .../account-activation/account-activation.tsx | 18 +- .../forgot-password-page.stories.tsx | 26 +++ .../forgot-password-page.tsx | 26 +++ .../reset-password-page.tsx | 44 +++++ .../reset-password-public-page.stories.tsx | 45 +++++ .../signin-page/signin-page.tsx | 23 +++ .../signin-public-page.stories.tsx | 26 +++ .../signup-page/signup-page.tsx | 29 +++ .../signup-public-page.stories.tsx | 39 ++++ .../signup-signin-base.stories.tsx | 23 +++ .../signup-signin-base.styles.ts | 61 ++++++ .../signup-signin-base/signup-signin-base.tsx | 55 ++++++ frontend/src/containers/account-activation.ts | 2 +- frontend/src/images/login_bg_animated.svg | 177 ++++++++++++++++++ frontend/src/images/trees_left.svg | 76 ++++++++ frontend/src/main/routes.js | 11 +- 23 files changed, 832 insertions(+), 22 deletions(-) create mode 100644 frontend/src/components/areas/public/features/session/pages/account-activation-page.tsx create mode 100644 frontend/src/components/areas/public/features/session/pages/session-page.tsx create mode 100644 frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx create mode 100644 frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts create mode 100644 frontend/src/components/design-library/molecules/cards/spot-card/spot-card.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.stories.tsx rename frontend/src/components/{areas/private/features/account/features => design-library/pages/public-pages/session-public-pages}/account-activation/account-activation.tsx (79%) create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx create mode 100644 frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx create mode 100644 frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx create mode 100644 frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts create mode 100644 frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.tsx create mode 100644 frontend/src/images/login_bg_animated.svg create mode 100644 frontend/src/images/trees_left.svg diff --git a/frontend/.storybook/main.js b/frontend/.storybook/main.js index f5d28d9c9..7583909a3 100644 --- a/frontend/.storybook/main.js +++ b/frontend/.storybook/main.js @@ -18,11 +18,10 @@ module.exports = { webpackFinal: async (config) => { config.resolve.alias = { ...config.resolve.alias, - images: path.resolve(__dirname, "../src/images"), // Add your alias - app: path.resolve(__dirname, "../src"), // Add your alias - "images": path.resolve(__dirname, "../src/images"), // Add your alias - "design-library": path.resolve(__dirname, "../src/components/design-library"), // Add your alias - "@material-ui/core": "@mui/material", // map MUI v4 import to MUI v5 if present + images: path.resolve(__dirname, "../src/images"), + app: path.resolve(__dirname, "../src"), + "images": path.resolve(__dirname, "../src/images"), + "design-library": path.resolve(__dirname, "../src/components/design-library"), }; config.resolve.fallback = { ...config.resolve.fallback, diff --git a/frontend/src/components/areas/public/features/session/pages/account-activation-page.tsx b/frontend/src/components/areas/public/features/session/pages/account-activation-page.tsx new file mode 100644 index 000000000..f232e6a55 --- /dev/null +++ b/frontend/src/components/areas/public/features/session/pages/account-activation-page.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import AccountActivation from 'design-library/pages/public-pages/session-public-pages/account-activation/account-activation'; + +const AccountActivationPage = ({ + activateAccount, +}) => { + + return ; +} + +export default AccountActivationPage; \ No newline at end of file diff --git a/frontend/src/components/areas/public/features/session/pages/session-page.tsx b/frontend/src/components/areas/public/features/session/pages/session-page.tsx new file mode 100644 index 000000000..f0089efe1 --- /dev/null +++ b/frontend/src/components/areas/public/features/session/pages/session-page.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { HashRouter, Route, Switch } from 'react-router-dom'; +import SignupSigninPage from 'design-library/templates/base/signup-signin-base/signup-signin-base'; +import AccountActivation from '../../../../../../containers/account-activation' +import LoginPageContainer from '../../../../../../containers/login-page' + +const SessionPage = () => { + return ( + + + + + + + + + + + + + ); +}; + +export default SessionPage; + diff --git a/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx new file mode 100644 index 000000000..d04304cd8 --- /dev/null +++ b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; +import SpotCard from './spot-card'; + +const meta: Meta = { + title: 'Design Library/Molecules/Cards/SpotCard', + component: SpotCard, +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + render: (args) => , + args: { + // Adjust these props to match SpotCard's API. They are placeholders. + title: 'Spot title', + subtitle: 'Optional subtitle', + children: 'This is a spot card description.', + } as any, +}; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts new file mode 100644 index 000000000..473529f18 --- /dev/null +++ b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts @@ -0,0 +1,18 @@ +import { Card, CardContent } from '@mui/material'; +import { styled } from '@mui/material/styles'; + +export const StyledCard = styled(Card)(() => ({ + minWidth: 420, + marginTop: 40, + opacity: 0.8, + overflow: 'visible' +})) + +export const StyledCardContent = styled(CardContent)(() => ({ + textAlign: 'center', + position: 'relative' +})) + +export const Content = styled('div')({ + marginTop: 20, +}); \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.tsx b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.tsx new file mode 100644 index 000000000..decde768f --- /dev/null +++ b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.tsx @@ -0,0 +1,88 @@ +import React, { useState } from 'react'; +import { Link } from 'react-router-dom'; +import { FormattedMessage } from 'react-intl'; +import { Typography, Dialog } from '@mui/material'; +import CookiePolicy from 'design-library/molecules/content/terms/cookie-policy/cookie-policy'; +import PrivacyPolicy from 'design-library/molecules/content/terms/privacy-policy/privacy-policy'; +import TermsOfService from 'design-library/molecules/content/terms/terms-of-service/terms-of-service'; +import { StyledCard, StyledCardContent, Content } from './spot-card.styles'; + +import logo from 'images/logo-complete.png' + +const SpotCard = ({ + title, + description, + children +}) => { + const [openDialog, setOpenDialog] = useState(false) + const [dialogType, setDialogType] = useState(null) + + const handleOpenDialog = (e, type) => { + e.preventDefault() + setDialogType(type) + setOpenDialog(true) + } + + const renderDialog = () => { + if (dialogType === 'cookie') { + return + } + if (dialogType === 'privacy') { + return + } + if (dialogType === 'terms') { + return + } + } + + const closeDialog = () => { + setOpenDialog(false) + setDialogType(null) + } + + return ( + <> + + + + Logo + + + + {title} + + + {description} + +
+ {children} +
+
+
+
+
+ + + handleOpenDialog(e, 'cookie')} style={{ display: 'inline-block', margin: '0 5px' }}> + + + | + handleOpenDialog(e, 'privacy')} style={{ display: 'inline-block', margin: '0 5px' }}> + + + | + handleOpenDialog(e, 'terms')} style={{ display: 'inline-block', margin: '0 5px' }}> + + + + +
+ {renderDialog()} +
+
+
+ + ); +}; + +export default SpotCard; \ No newline at end of file diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.stories.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/src/components/areas/private/features/account/features/account-activation/account-activation.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.tsx similarity index 79% rename from frontend/src/components/areas/private/features/account/features/account-activation/account-activation.tsx rename to frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.tsx index 5c0abc7ae..c369f625e 100644 --- a/frontend/src/components/areas/private/features/account/features/account-activation/account-activation.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.tsx @@ -6,19 +6,23 @@ import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import { FormattedMessage } from 'react-intl'; -const AccountActivation = ({ activateAccount, match, history }) => { +const AccountActivation = ({ onActivateAccount }) => { const [open, setOpen] = React.useState(false); const [ activated, setActivated ] = React.useState(false); + const { token, userId } = useParams<{ token: string; userId: string }>(); + useEffect(() => { - const token = match.params.token; - const userId = match.params.userId; - activateAccount(token, userId).then((data) => { - if (!data.error) { + const activate = async () => { + const token = match.params.token; + const userId = match.params.userId; + const activateAccount = await onActivateAccount(token, userId); + if(!activateAccount.error){ setActivated(true); } - }); - setOpen(true); + setOpen(true); + }; + activate(); }, []); return ( diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx new file mode 100644 index 000000000..6dcd09c48 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { withSignupSigninBaseTemplate } from '../../../../../../../.storybook/decorators/withPublicTemplate'; +import ForgotPasswordPage from './forgot-password-page'; + +const meta: Meta = { + title: 'Design Library/Pages/Public/Session/ForgotPassword', + decorators: [ withSignupSigninBaseTemplate ], + component: ForgotPasswordPage +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; + +export const WithError: Story = { + args: { + error: 'Unable to load session data', + }, +}; + +export const AlternateSession: Story = { + args: { + sessionId: 'another-session-id', + }, +}; diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx new file mode 100644 index 000000000..ff0d39021 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import SpotCard from 'design-library/molecules/cards/spot-card/spot-card'; +import LoginFormForgot from 'design-library/molecules/form-section/login-form/login-form-forgot/login-form-forgot'; +import { useHistory } from 'react-router-dom'; + +const ForgotUserPage = ({ + forgotPassword, +}) => { + const history = useHistory() + return ( + } + description={} + > + history.push('/signin')} + onClose={() => history.push('/')} + onSubmit={forgotPassword} + noCancelButton + /> + + ); +}; + +export default ForgotUserPage; diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx new file mode 100644 index 000000000..e815cad88 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { Skeleton } from '@mui/material'; +import SpotCard from 'design-library/molecules/cards/spot-card/spot-card'; +import LoginFormReset from 'design-library/molecules/form-section/login-form/login-form-reset/login-form-reset'; +import { FormattedMessage } from 'react-intl'; +import { useHistory } from 'react-router-dom'; + +const ResetPasswordPage = ({ + user, + resetPassword, +}) => { + const history = useHistory() + const { data, completed } = user || {} + + return ( + } + description={ + completed ? +
+ {chunks}, + br:
+ }} + /> +
: + } + > + history.push('/signin')} + onClose={() => history.push('/')} + onReset={resetPassword} + noCancelButton + /> +
+ ); +}; + +export default ResetPasswordPage; diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx new file mode 100644 index 000000000..e0d3716f8 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx @@ -0,0 +1,45 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { withSignupSigninBaseTemplate } from '../../../../../../../.storybook/decorators/withPublicTemplate'; +import ResetPasswordPage from './reset-password-page'; + +const meta: Meta = { + title: 'Design Library/Pages/Public/Session/ResetPassword', + decorators: [ withSignupSigninBaseTemplate ], + component: ResetPasswordPage +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + user: { + completed: true, + data: { + username: 'john_doe', + email: 'john_doe@example.com' + } + }, + }, +}; + +export const Loading: Story = { + args: { + user: { + completed: false, + data: {} + } + }, +}; + +export const WithError: Story = { + args: { + error: 'Unable to load session data', + }, +}; + +export const AlternateSession: Story = { + args: { + sessionId: 'another-session-id', + }, +}; diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx new file mode 100644 index 000000000..22533689e --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx @@ -0,0 +1,23 @@ +import SpotCard from 'design-library/molecules/cards/spot-card/spot-card'; +import LoginFormSignin from 'design-library/molecules/form-section/login-form/login-form-signin/login-form-signin'; +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { useHistory } from 'react-router-dom'; + +const SigninPage = ({}) => { + const history = useHistory(); + return ( + } + description={} + > + history.push('/signup')} + onForgot={() => history.push('/forgot')} + noCancelButton + /> + + ); +}; + +export default SigninPage; \ No newline at end of file diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx new file mode 100644 index 000000000..04f46da21 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { withSignupSigninBaseTemplate } from '../../../../../../../.storybook/decorators/withPublicTemplate'; +import SigninPage from './signin-page'; + +const meta: Meta = { + title: 'Design Library/Pages/Public/Session/Signin', + decorators: [ withSignupSigninBaseTemplate ], + component: SigninPage +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; + +export const WithError: Story = { + args: { + error: 'Unable to load session data', + }, +}; + +export const AlternateSession: Story = { + args: { + sessionId: 'another-session-id', + }, +}; \ No newline at end of file diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx new file mode 100644 index 000000000..3588768c3 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx @@ -0,0 +1,29 @@ +import SpotCard from 'design-library/molecules/cards/spot-card/spot-card'; +import LoginFormSignup from 'design-library/molecules/form-section/login-form/login-form-signup/login-form-signup'; +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import { useHistory } from 'react-router-dom'; + +const SignupPage = ({ + handleSignup, + roles, + fetchRoles, +}) => { + const history = useHistory(); + return ( + } + description={} + > + history.push('/signin')} + onSubmit={handleSignup} + roles={roles} + fetchRoles={fetchRoles} + noCancelButton + /> + + ); +}; + +export default SignupPage; \ No newline at end of file diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx new file mode 100644 index 000000000..c436252a9 --- /dev/null +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx @@ -0,0 +1,39 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { withSignupSigninBaseTemplate } from '../../../../../../../.storybook/decorators/withPublicTemplate'; +import SignupPage from './signup-page'; + +const meta: Meta = { + title: 'Design Library/Pages/Public/Session/Signup', + decorators: [ withSignupSigninBaseTemplate ], + component: SignupPage +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + handleSignup: () => {}, + roles: { + completed: true, + data: [ + { name: 'contributor', label: 'Contributor' }, + { name: 'maintainer', label: 'Maintainer' }, + { name: 'sponsor', label: 'Sponsor' } + ] + }, + fetchRoles: () => {}, + }, +}; + +export const WithError: Story = { + args: { + error: 'Unable to load session data', + }, +}; + +export const AlternateSession: Story = { + args: { + sessionId: 'another-session-id', + }, +}; diff --git a/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx new file mode 100644 index 000000000..04e593f8d --- /dev/null +++ b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx @@ -0,0 +1,23 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import React from 'react'; +import SignupSigninBase from './signup-signin-base'; + +const meta: Meta = { + title: 'Design Library/Templates/Base/SignupSigninBase', + component: SignupSigninBase, + parameters: { + layout: 'fullscreen', + }, + args: { + children:
Default Content
, + } +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + + }, +}; \ No newline at end of file diff --git a/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts new file mode 100644 index 000000000..1be2ae5d7 --- /dev/null +++ b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts @@ -0,0 +1,61 @@ +import { styled, keyframes } from '@mui/material/styles'; + +const driftSlow = keyframes` + 0% { transform: translateX(-20vw); } + 100% { transform: translateX(120vw); } +`; +const driftMed = keyframes` + 0% { transform: translateX(-30vw); } + 100% { transform: translateX(130vw); } +`; +const driftFast = keyframes` + 0% { transform: translateX(-40vw); } + 100% { transform: translateX(140vw); } +`; + +export const GradientBackground = styled('div')(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '100%', + position: 'relative', + overflow: 'hidden', + minHeight: '100vh', + backgroundImage: [ + 'radial-gradient(120% 120% at 30% 0%, #eaf3ff 0%, #edf5f2 30%, #e9f1ed 55%, #e3eee8 75%, #d9e7df 100%)', + 'radial-gradient(140% 140% at 90% -10%, rgba(176,209,238,0.25), rgba(176,209,238,0) 70%)' + ].join(', '), + backgroundRepeat: 'no-repeat, no-repeat', + backgroundAttachment: 'fixed, fixed', + backgroundSize: '160% 160%, 140% 140%', + backgroundPosition: '35% 0%, 60% 20%', + '@media (prefers-reduced-motion: reduce)': { + animation: 'none' + } +})); + +export const CloudsLayer = styled('div')({ + position: 'absolute', + inset: 0, + pointerEvents: 'none', + zIndex: 2, +}); + +export const Cloud = styled('div')< + { $duration?: string; $delay?: string; $blur?: number; $scale?: number; $y?: string; $variant?: 'slow' | 'med' | 'fast' } +>(({ $duration = '60s', $delay = '0s', $blur = 0, $scale = 1, $y = '0vh', $variant = 'slow' }) => { + const animation = $variant === 'fast' ? driftFast : $variant === 'med' ? driftMed : driftSlow; + return { + position: 'absolute', + top: $y, + left: '-30vw', + transform: `translateX(-30vw) scale(${$scale})`, + filter: $blur ? `blur(${$blur}px)` : 'none', + animation: `${animation} ${$duration} linear infinite`, + animationDelay: $delay, + '@media (prefers-reduced-motion: reduce)': { + animation: 'none', + transform: `translateX(0) scale(${$scale})` + } + }; +}); diff --git a/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.tsx b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.tsx new file mode 100644 index 000000000..b6ece24ef --- /dev/null +++ b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { GradientBackground, CloudsLayer, Cloud } from './signup-signin-base.styles'; + +const CloudSvg = ({ colorA = '#eaf3ff', colorB = '#cfe2fb', colorC = '#a8c9ee', opacity = 1, style = {} }) => ( + + + + + + + + + + + + + + + + + +); + +export default function SignupSigninBase({ children }) { + return ( + + + + + + + + + + + + + + + + + + + + + +
+ {children} +
+
+ ); +} diff --git a/frontend/src/containers/account-activation.ts b/frontend/src/containers/account-activation.ts index cff8ac07e..cfb53cda7 100644 --- a/frontend/src/containers/account-activation.ts +++ b/frontend/src/containers/account-activation.ts @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import { activateUser } from '../actions/userActions'; -import AccountActivation from '../components/areas/private/features/account/features/account-activation/account-activation'; +import AccountActivation from '../components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation'; const mapDispatchToProps = (dispatch) => ({ activateAccount: (token: string, userId: number) => dispatch(activateUser(userId, token)) diff --git a/frontend/src/images/login_bg_animated.svg b/frontend/src/images/login_bg_animated.svg new file mode 100644 index 000000000..9c4857126 --- /dev/null +++ b/frontend/src/images/login_bg_animated.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/images/trees_left.svg b/frontend/src/images/trees_left.svg new file mode 100644 index 000000000..b147c1e10 --- /dev/null +++ b/frontend/src/images/trees_left.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/main/routes.js b/frontend/src/main/routes.js index 59207c767..abf3fe30d 100644 --- a/frontend/src/main/routes.js +++ b/frontend/src/main/routes.js @@ -4,8 +4,7 @@ import PrivateRoute from '../components/areas/private/components/session/private import PublicPageContainer from '../containers/public-container' import Session from '../components/areas/private/components/session/session' import ProfileContainer from '../containers/profile' -import AccountActivation from '../containers/account-activation' -import LoginPageContainer from '../containers/login-page' + import FourOFour from '../components/design-library/pages/public-pages/four-o-four-public-page/four-o-four-public-page' import Stats from '../components/areas/public/features/stats/Stats-main-page' import TaskListUser from '../containers/task-list-user' @@ -21,13 +20,7 @@ export default props => ( {/* Private area needs to appear before the broad "/" route */} - - - - - - - + From 782fe40ec78271b2430a71f4dcdff39dec09d9f4 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Sun, 9 Nov 2025 13:03:48 +0100 Subject: [PATCH 16/19] login and signup flows --- .../components/session/cookie-policy.tsx | 2 +- .../features/session/components/session.tsx | 24 +++++++++++++++++ .../features/session/pages/forgot-page.tsx | 13 ++++++++++ .../features/session/pages/reset-page.tsx | 13 ++++++++++ .../features/session/pages/session-page.tsx | 8 ++++-- .../features/session/pages/signin-page.tsx | 14 ++++++++++ .../features/session/pages/signup-page.tsx | 18 +++++++++++++ .../terms/cookie-policy/cookie-policy.tsx | 2 +- .../login-form-signin/login-form-signin.tsx | 26 ++++++++++++------- .../account-activation/account-activation.tsx | 4 +-- .../signin-page/signin-page.tsx | 5 +++- frontend/src/containers/account-activation.ts | 2 +- frontend/src/containers/login-page.js | 4 +-- frontend/src/containers/register-page.js | 24 +++++++++++++++++ frontend/src/main/routes.js | 12 ++------- 15 files changed, 141 insertions(+), 30 deletions(-) create mode 100644 frontend/src/components/areas/public/features/session/components/session.tsx create mode 100644 frontend/src/components/areas/public/features/session/pages/forgot-page.tsx create mode 100644 frontend/src/components/areas/public/features/session/pages/reset-page.tsx create mode 100644 frontend/src/components/areas/public/features/session/pages/signin-page.tsx create mode 100644 frontend/src/components/areas/public/features/session/pages/signup-page.tsx create mode 100644 frontend/src/containers/register-page.js diff --git a/frontend/src/components/areas/private/components/session/cookie-policy.tsx b/frontend/src/components/areas/private/components/session/cookie-policy.tsx index 3a08e8ad6..9a3dcbd0f 100644 --- a/frontend/src/components/areas/private/components/session/cookie-policy.tsx +++ b/frontend/src/components/areas/private/components/session/cookie-policy.tsx @@ -49,7 +49,7 @@ We may update this Cookie Policy from time to time to reflect changes in our pra {br}{br} Contact us {br}{br} -If you have any questions or concerns about this Cookie Policy or our use of cookies on Gitpay, please contact us at [insert contact information]. +If you have any questions or concerns about this Cookie Policy or our use of cookies on Gitpay, please contact us at contact@gitpay.me. {br} Please note that this Cookie Policy should be read in conjunction with our Privacy Policy, which provides further information on how we collect, use, and disclose your personal data. ` diff --git a/frontend/src/components/areas/public/features/session/components/session.tsx b/frontend/src/components/areas/public/features/session/components/session.tsx new file mode 100644 index 000000000..3f39d8eab --- /dev/null +++ b/frontend/src/components/areas/public/features/session/components/session.tsx @@ -0,0 +1,24 @@ +import { useEffect } from 'react' +import Auth from '../../../../../../modules/auth' +import { useHistory, useParams } from 'react-router-dom' + +const Session = () => { + const history = useHistory() + const { token } = useParams<{ token: string }>() + + useEffect(() => { + const referer = Auth.getReferer() + + Auth.authenticateUser(token) + + if (referer && referer !== '/') { + history.replace(referer) + } else { + history.replace('/profile') + } + }, [token, history]) + + return null +} + +export default Session diff --git a/frontend/src/components/areas/public/features/session/pages/forgot-page.tsx b/frontend/src/components/areas/public/features/session/pages/forgot-page.tsx new file mode 100644 index 000000000..7aa186866 --- /dev/null +++ b/frontend/src/components/areas/public/features/session/pages/forgot-page.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import ForgotPasswordPage from 'design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page'; + +const ForgotPage = ({ + forgotPassword, +}) => { + return ( + + ); +}; +export default ForgotPage; \ No newline at end of file diff --git a/frontend/src/components/areas/public/features/session/pages/reset-page.tsx b/frontend/src/components/areas/public/features/session/pages/reset-page.tsx new file mode 100644 index 000000000..a83f5fbf5 --- /dev/null +++ b/frontend/src/components/areas/public/features/session/pages/reset-page.tsx @@ -0,0 +1,13 @@ +import React from "react" +import ResetPasswordPage from "design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page" + +const ResetPage = ({ user, resetPassword }) => { + return ( + + ); +} + +export default ResetPage; \ No newline at end of file diff --git a/frontend/src/components/areas/public/features/session/pages/session-page.tsx b/frontend/src/components/areas/public/features/session/pages/session-page.tsx index f0089efe1..14ed40bc8 100644 --- a/frontend/src/components/areas/public/features/session/pages/session-page.tsx +++ b/frontend/src/components/areas/public/features/session/pages/session-page.tsx @@ -1,8 +1,10 @@ import React from 'react'; import { HashRouter, Route, Switch } from 'react-router-dom'; import SignupSigninPage from 'design-library/templates/base/signup-signin-base/signup-signin-base'; +import Session from '../components/session'; import AccountActivation from '../../../../../../containers/account-activation' import LoginPageContainer from '../../../../../../containers/login-page' +import RegisterPageContainer from '../../../../../../containers/register-page' const SessionPage = () => { return ( @@ -11,10 +13,12 @@ const SessionPage = () => { - + + - + + diff --git a/frontend/src/components/areas/public/features/session/pages/signin-page.tsx b/frontend/src/components/areas/public/features/session/pages/signin-page.tsx new file mode 100644 index 000000000..d4e77204c --- /dev/null +++ b/frontend/src/components/areas/public/features/session/pages/signin-page.tsx @@ -0,0 +1,14 @@ +import React from 'react' +import SigninPageTemplate from 'design-library/pages/public-pages/session-public-pages/signin-page/signin-page' + +const SigninPage = ({ + addNotification, +}) => { + return ( + + ) +} + +export default SigninPage \ No newline at end of file diff --git a/frontend/src/components/areas/public/features/session/pages/signup-page.tsx b/frontend/src/components/areas/public/features/session/pages/signup-page.tsx new file mode 100644 index 000000000..0625bb5b8 --- /dev/null +++ b/frontend/src/components/areas/public/features/session/pages/signup-page.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import SignupPageTemplate from 'design-library/pages/public-pages/session-public-pages/signup-page/signup-page' + +const SignupPage = ({ + fetchRoles, + registerUser, + roles, +}) => { + return ( + + ) +} + +export default SignupPage \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.tsx b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.tsx index 0e182090e..e424cd898 100644 --- a/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.tsx @@ -49,7 +49,7 @@ We may update this Cookie Policy from time to time to reflect changes in our pra {br}{br} Contact us {br}{br} -If you have any questions or concerns about this Cookie Policy or our use of cookies on Gitpay, please contact us at [insert contact information]. +If you have any questions or concerns about this Cookie Policy or our use of cookies on Gitpay, please contact us at contact@gitpay.me. {br} Please note that this Cookie Policy should be read in conjunction with our Privacy Policy, which provides further information on how we collect, use, and disclose your personal data. ` diff --git a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx index d36361b4b..1a6500d49 100644 --- a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx +++ b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx @@ -10,17 +10,21 @@ import ProviderLoginButtons from '../../../../atoms/buttons/provider-login-butto import api from '../../../../../../consts' import { Margins, Center, SpacedButton, StyledTextField } from './login-form-signin.styles' +import { useParams } from 'react-router-dom' type LoginFormSigninProps = { onSubmit?: (event: React.FormEvent) => void action?: string onClose?: () => void onSignup?: () => void - noCancelButton?: boolean, + noCancelButton?: boolean onForgot?: () => void + addNotification?: (message: string) => void } -const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot }:LoginFormSigninProps) => { +const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot, addNotification }: LoginFormSigninProps) => { + const { status } = useParams<{ status: string }>() + const [state, setState] = useState({ username: '', password: '', @@ -45,10 +49,6 @@ const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot setState({ ...state, rememberMe: !state.rememberMe }) } - const handleType = (type) => { - // handle type logic - } - const validateEmail = (email, currentErrors) => { if (email.length < 3) { setState({ @@ -59,7 +59,7 @@ const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot } }) return false - } else if(email.length > 72) { + } else if (email.length > 72) { setState({ ...state, error: { @@ -94,7 +94,7 @@ const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot } }) return false - } else if(password.length > 72) { + } else if (password.length > 72) { setState({ ...state, error: { @@ -117,7 +117,7 @@ const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot } const validEmail = validateEmail(state.username, state.error) const validPassword = validatePassword(state.password, state.error) - if(!validEmail || !validPassword) { + if (!validEmail || !validPassword) { return event && event.preventDefault(); } onSubmit?.(event) @@ -128,6 +128,12 @@ const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot process.env.NODE_ENV === 'test' && setState({ ...state, captchaChecked: true }) }, []) + useEffect(() => { + if (status === 'invalid') { + addNotification && addNotification('user.invalid') + } + }, [status, addNotification]) + const { error } = state return ( @@ -221,7 +227,7 @@ const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot
- + ) } diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.tsx index c369f625e..b9936bbfc 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation.tsx @@ -5,17 +5,17 @@ import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import { FormattedMessage } from 'react-intl'; +import { useHistory, useParams } from 'react-router-dom'; const AccountActivation = ({ onActivateAccount }) => { const [open, setOpen] = React.useState(false); const [ activated, setActivated ] = React.useState(false); + const history = useHistory(); const { token, userId } = useParams<{ token: string; userId: string }>(); useEffect(() => { const activate = async () => { - const token = match.params.token; - const userId = match.params.userId; const activateAccount = await onActivateAccount(token, userId); if(!activateAccount.error){ setActivated(true); diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx index 22533689e..2451b3891 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx @@ -4,7 +4,9 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import { useHistory } from 'react-router-dom'; -const SigninPage = ({}) => { +const SigninPage = ({ + addNotification, +}) => { const history = useHistory(); return ( { description={} > history.push('/signup')} onForgot={() => history.push('/forgot')} noCancelButton diff --git a/frontend/src/containers/account-activation.ts b/frontend/src/containers/account-activation.ts index cfb53cda7..382aca4b1 100644 --- a/frontend/src/containers/account-activation.ts +++ b/frontend/src/containers/account-activation.ts @@ -1,6 +1,6 @@ import { connect } from 'react-redux'; import { activateUser } from '../actions/userActions'; -import AccountActivation from '../components/design-library/pages/public-pages/session-public-pages/account-activation/account-activation'; +import AccountActivation from '../components/areas/public/features/session/pages/account-activation-page'; const mapDispatchToProps = (dispatch) => ({ activateAccount: (token: string, userId: number) => dispatch(activateUser(userId, token)) diff --git a/frontend/src/containers/login-page.js b/frontend/src/containers/login-page.js index fe2dfb31b..7abf56fdd 100644 --- a/frontend/src/containers/login-page.js +++ b/frontend/src/containers/login-page.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import { addNotification } from '../actions/notificationActions' import { registerUser, forgotPassword, resetPassword } from '../actions/loginActions' import { fetchRoles } from '../actions/userRoleActions' -import LoginPage from '../components/areas/private/components/session/login-page' +import SigninPage from '../components/areas/public/features/session/pages/signin-page' const mapStateToProps = (state, props) => { return { @@ -21,4 +21,4 @@ const mapDispatchToProps = (dispatch, ownProps) => { } } -export default connect(mapStateToProps, mapDispatchToProps)(LoginPage) +export default connect(mapStateToProps, mapDispatchToProps)(SigninPage) diff --git a/frontend/src/containers/register-page.js b/frontend/src/containers/register-page.js new file mode 100644 index 000000000..440bcdace --- /dev/null +++ b/frontend/src/containers/register-page.js @@ -0,0 +1,24 @@ +import { connect } from 'react-redux' +import { addNotification } from '../actions/notificationActions' +import { registerUser, forgotPassword, resetPassword } from '../actions/loginActions' +import { fetchRoles } from '../actions/userRoleActions' +import SignupPage from '../components/areas/public/features/session/pages/signup-page' + +const mapStateToProps = (state, props) => { + return { + user: state.user, + roles: state.roles + } +} + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + addNotification: (msg) => dispatch(addNotification(msg)), + fetchRoles: () => dispatch(fetchRoles()), + registerUser: (data) => dispatch(registerUser(data)), + forgotPassword: (data) => dispatch(forgotPassword(data)), + resetPassword: (data) => dispatch(resetPassword(data)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(SignupPage) diff --git a/frontend/src/main/routes.js b/frontend/src/main/routes.js index abf3fe30d..9bee2a368 100644 --- a/frontend/src/main/routes.js +++ b/frontend/src/main/routes.js @@ -2,8 +2,8 @@ import React from 'react' import { Route, HashRouter, Switch, Redirect } from 'react-router-dom' import PrivateRoute from '../components/areas/private/components/session/private-route' import PublicPageContainer from '../containers/public-container' -import Session from '../components/areas/private/components/session/session' import ProfileContainer from '../containers/profile' +import SessionPage from '../components/areas/public/features/session/pages/session-page' import FourOFour from '../components/design-library/pages/public-pages/four-o-four-public-page/four-o-four-public-page' import Stats from '../components/areas/public/features/stats/Stats-main-page' @@ -13,14 +13,7 @@ import Auth from '../modules/auth' export default props => ( - {/* */} - - {/* Make sure token auth happens before the broad "/" route */} - - - {/* Private area needs to appear before the broad "/" route */} - @@ -34,8 +27,7 @@ export default props => ( : } /> - - {/* Keep this AFTER specific routes so they can match */} + From 4ca260e9b74d457f706438dba2dd2d6f31d15a68 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Mon, 10 Nov 2025 01:13:02 +0100 Subject: [PATCH 17/19] all the account activation and forgot flows into design library --- frontend/src/actions/loginActions.js | 2 +- .../features/session/pages/reset-page.tsx | 13 +++++- .../features/session/pages/session-page.tsx | 6 ++- .../activate-account-dialog.tsx | 45 ++++++++++++++++--- .../login-form-signin/login-form-signin.tsx | 2 +- .../src/containers/forgot-password-page.js | 24 ++++++++++ .../src/containers/reset-password-page.js | 25 +++++++++++ frontend/src/reducers/loginReducer.js | 2 +- 8 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 frontend/src/containers/forgot-password-page.js create mode 100644 frontend/src/containers/reset-password-page.js diff --git a/frontend/src/actions/loginActions.js b/frontend/src/actions/loginActions.js index c3b4aa1d7..169783ec0 100644 --- a/frontend/src/actions/loginActions.js +++ b/frontend/src/actions/loginActions.js @@ -286,7 +286,7 @@ const searchUserRequested = () => { } const searchUserSuccess = user => { - return { type: SEARCH_USER_SUCCESS, logged: false, completed: true, user: user } + return { type: SEARCH_USER_SUCCESS, logged: false, completed: true, data: user } } const searchUserError = error => { diff --git a/frontend/src/components/areas/public/features/session/pages/reset-page.tsx b/frontend/src/components/areas/public/features/session/pages/reset-page.tsx index a83f5fbf5..8bf586c8a 100644 --- a/frontend/src/components/areas/public/features/session/pages/reset-page.tsx +++ b/frontend/src/components/areas/public/features/session/pages/reset-page.tsx @@ -1,7 +1,16 @@ -import React from "react" +import React, { useEffect } from "react" import ResetPasswordPage from "design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page" +import { useParams } from "react-router-dom"; + +const ResetPage = ({ user, searchUser, resetPassword }) => { + const { token } = useParams<{ token: string }>() + + useEffect(() => { + if (token) { + searchUser({ recover_password_token: token }) + } + }, [token, searchUser]) -const ResetPage = ({ user, resetPassword }) => { return ( { return ( @@ -14,11 +16,11 @@ const SessionPage = () => { - + - + diff --git a/frontend/src/components/design-library/molecules/dialogs/activate-account-dialog/activate-account-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/activate-account-dialog/activate-account-dialog.tsx index 14ff5390c..9028dbdfb 100644 --- a/frontend/src/components/design-library/molecules/dialogs/activate-account-dialog/activate-account-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/activate-account-dialog/activate-account-dialog.tsx @@ -1,9 +1,38 @@ import { Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material'; -import React from 'react'; +import React, { useEffect, useState, useCallback } from 'react'; import { FormattedMessage } from 'react-intl'; import Button from '../../../atoms/buttons/button/button'; -const ActivateAccountDialog = ({ open, onResend, completed }) => { +interface ActivateAccountDialogProps { + open: boolean; + onResend: () => void; + completed?: boolean; +} + +const RESEND_COOLDOWN_SECONDS = 60; + +const ActivateAccountDialog: React.FC = ({ open, onResend, completed }) => { + const [cooldown, setCooldown] = useState(0); + + useEffect(() => { + if (cooldown <= 0) return; + const timer = setInterval(() => { + setCooldown(prev => (prev > 1 ? prev - 1 : 0)); + }, 1000); + return () => clearInterval(timer); + }, [cooldown]); + + const handleResend = useCallback(() => { + if (cooldown > 0) return; + onResend?.(); + setCooldown(RESEND_COOLDOWN_SECONDS); + }, [cooldown, onResend]); + + const buttonLabel = + cooldown > 0 + ? + : ; + return ( @@ -28,20 +57,22 @@ const ActivateAccountDialog = ({ open, onResend, completed }) => { - ); -} +}; + export default ActivateAccountDialog; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx index 1a6500d49..be5741c69 100644 --- a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx +++ b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signin/login-form-signin.tsx @@ -178,7 +178,7 @@ const LoginFormSignin = ({ onSubmit, onClose, onSignup, noCancelButton, onForgot
-
diff --git a/frontend/src/containers/forgot-password-page.js b/frontend/src/containers/forgot-password-page.js new file mode 100644 index 000000000..082a3d354 --- /dev/null +++ b/frontend/src/containers/forgot-password-page.js @@ -0,0 +1,24 @@ +import { connect } from 'react-redux' +import { addNotification } from '../actions/notificationActions' +import { registerUser, forgotPassword, resetPassword } from '../actions/loginActions' +import { fetchRoles } from '../actions/userRoleActions' +import ForgotPasswordPage from '../components/areas/public/features/session/pages/forgot-page' + +const mapStateToProps = (state, props) => { + return { + user: state.user, + roles: state.roles + } +} + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + addNotification: (msg) => dispatch(addNotification(msg)), + fetchRoles: () => dispatch(fetchRoles()), + registerUser: (data) => dispatch(registerUser(data)), + forgotPassword: (data) => dispatch(forgotPassword(data)), + resetPassword: (data) => dispatch(resetPassword(data)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(ForgotPasswordPage) diff --git a/frontend/src/containers/reset-password-page.js b/frontend/src/containers/reset-password-page.js new file mode 100644 index 000000000..b8271c29d --- /dev/null +++ b/frontend/src/containers/reset-password-page.js @@ -0,0 +1,25 @@ +import { connect } from 'react-redux' +import { addNotification } from '../actions/notificationActions' +import { registerUser, forgotPassword, resetPassword, searchUser } from '../actions/loginActions' +import { fetchRoles } from '../actions/userRoleActions' +import ResetPasswordPage from '../components/areas/public/features/session/pages/reset-page' + +const mapStateToProps = (state, props) => { + return { + user: state.loggedIn, + roles: state.roles + } +} + +const mapDispatchToProps = (dispatch, ownProps) => { + return { + addNotification: (msg) => dispatch(addNotification(msg)), + fetchRoles: () => dispatch(fetchRoles()), + registerUser: (data) => dispatch(registerUser(data)), + forgotPassword: (data) => dispatch(forgotPassword(data)), + resetPassword: (data) => dispatch(resetPassword(data)), + searchUser: (data) => dispatch(searchUser(data)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(ResetPasswordPage) diff --git a/frontend/src/reducers/loginReducer.js b/frontend/src/reducers/loginReducer.js index 1cd5a7399..aa8144264 100644 --- a/frontend/src/reducers/loginReducer.js +++ b/frontend/src/reducers/loginReducer.js @@ -39,7 +39,7 @@ export const loggedIn = (state = { logged: false, data: {}, completed: true, err case LOGOUT_COMPLETED: return { ...state, logged: action.logged, completed: action.completed } case SEARCH_USER_SUCCESS: - return { ...state, user: action.data } + return { ...state, data: action.data } case SEARCH_USER_ERROR: return { ...state, error: action.error } case FETCH_LOGGED_USER_REQUESTED: From d24f0818bfcacc681d38a164061b0eb03da6f7f2 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Mon, 10 Nov 2025 01:14:14 +0100 Subject: [PATCH 18/19] lint fixes --- .../cards/spot-card/spot-card.stories.tsx | 6 ++--- .../cards/spot-card/spot-card.styles.ts | 2 +- .../terms/base-terms/base-terms.stories.tsx | 26 +++++++++---------- .../terms/base-terms/base-terms.styles.ts | 12 ++++----- .../cookie-policy/cookie-policy.stories.tsx | 10 +++---- .../privacy-policy/privacy-policy.stories.tsx | 8 +++--- .../terms-of-service.stories.tsx | 8 +++--- .../bottom-section-dialog.styles.ts | 4 +-- .../bottom-section-dialog.tsx | 16 ++++++------ .../dialogs/terms-dialog/terms-dialog.tsx | 3 +-- .../login-form-signup/login-form-signup.tsx | 2 +- .../vertical-menu-list.stories.tsx | 16 ++++++------ .../vertical-menu-list.styles.ts | 6 ++--- .../bottom-bar-layout/bottom-bar-layout.tsx | 2 +- .../pricing-public-page.tsx | 2 -- .../forgot-password-page.stories.tsx | 8 +++--- .../forgot-password-page.tsx | 2 +- .../reset-password-page.tsx | 2 +- .../reset-password-public-page.stories.tsx | 14 +++++----- .../signin-page/signin-page.tsx | 2 +- .../signin-public-page.stories.tsx | 8 +++--- .../signup-page/signup-page.tsx | 2 +- .../signup-public-page.stories.tsx | 12 ++++----- .../signup-signin-base.stories.tsx | 6 ++--- .../signup-signin-base.styles.ts | 2 +- 25 files changed, 89 insertions(+), 92 deletions(-) diff --git a/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx index d04304cd8..12d145443 100644 --- a/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx +++ b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.stories.tsx @@ -4,7 +4,7 @@ import SpotCard from './spot-card'; const meta: Meta = { title: 'Design Library/Molecules/Cards/SpotCard', - component: SpotCard, + component: SpotCard }; export default meta; @@ -17,6 +17,6 @@ export const Default: Story = { // Adjust these props to match SpotCard's API. They are placeholders. title: 'Spot title', subtitle: 'Optional subtitle', - children: 'This is a spot card description.', - } as any, + children: 'This is a spot card description.' + } as any }; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts index 473529f18..e0f2c644d 100644 --- a/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts +++ b/frontend/src/components/design-library/molecules/cards/spot-card/spot-card.styles.ts @@ -14,5 +14,5 @@ export const StyledCardContent = styled(CardContent)(() => ({ })) export const Content = styled('div')({ - marginTop: 20, + marginTop: 20 }); \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx index 990d472dc..15c82f358 100644 --- a/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.stories.tsx @@ -6,8 +6,8 @@ const meta: Meta = { title: "Design Library/Molecules/Content/Terms/BaseTerms", component: BaseTerms, parameters: { - layout: "centered", - }, + layout: "centered" + } }; export default meta; @@ -18,36 +18,36 @@ const baseArgs = { subtitle: "Please read these terms carefully before using our service.", updated: "Last updated: Jan 1, 2025", content: - "By accessing or using the service you agree to be bound by these Terms. If you disagree with any part of the terms then you may not access the service.", + "By accessing or using the service you agree to be bound by these Terms. If you disagree with any part of the terms then you may not access the service." // extraStyles defaults to true in the component }; export const Default: Story = { args: { - ...baseArgs, - }, + ...baseArgs + } }; export const WithActions: Story = { args: { ...baseArgs, onArrowBack: action("onArrowBack"), - onAgreeTerms: action("onAgreeTerms"), - }, + onAgreeTerms: action("onAgreeTerms") + } }; export const NoHeader: Story = { args: { ...baseArgs, - noHeader: true, - }, + noHeader: true + } }; export const WithoutExtraStyles: Story = { args: { ...baseArgs, - extraStyles: false, - }, + extraStyles: false + } }; export const LongContent: Story = { @@ -62,6 +62,6 @@ export const LongContent: Story = { "for any reason whatsoever, including without limitation if you breach the terms. " + "The service and its original content, features and functionality are and will remain the exclusive " + "property of the company and its licensors. " + - "We reserve the right, at our sole discretion, to modify or replace these terms at any time.", - }, + "We reserve the right, at our sole discretion, to modify or replace these terms at any time." + } }; diff --git a/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts index c50d88889..fd69dead7 100644 --- a/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts +++ b/frontend/src/components/design-library/molecules/content/terms/base-terms/base-terms.styles.ts @@ -14,18 +14,18 @@ export const TermsContainer = styled("div")(({ extraStyles top: 0, left: 0, width: "100%", - background: "white", + background: "white" } - : {}), + : {}) })); export const Header = styled("div")({ - marginBottom: 10, + marginBottom: 10 }); export const ContentArea = styled("div")({ overflow: "scroll", - height: "calc(100vh - 200px)", + height: "calc(100vh - 200px)" }); export const ActionsBar = styled(Paper)({ @@ -34,11 +34,11 @@ export const ActionsBar = styled(Paper)({ left: 0, height: 80, width: "100%", - background: "white", + background: "white" }); export const ActionButton = styled(Button)({ float: "right", marginRight: 20, - marginTop: 20, + marginTop: 20 }); diff --git a/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx index be0fca9c2..77fb09b74 100644 --- a/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/cookie-policy/cookie-policy.stories.tsx @@ -5,20 +5,20 @@ const meta: Meta = { title: 'Design Library/Molecules/Content/Terms/CookiePolicy', component: CookiePolicy, args: { - extraStyles: true, + extraStyles: true }, argTypes: { - extraStyles: { control: 'boolean' }, - }, + extraStyles: { control: 'boolean' } + } }; export default meta; type Story = StoryObj; export const Default: Story = { - args: { extraStyles: true }, + args: { extraStyles: true } }; export const NoExtraStyles: Story = { - args: { extraStyles: false }, + args: { extraStyles: false } }; diff --git a/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx index fe1d72596..602d8398d 100644 --- a/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/privacy-policy/privacy-policy.stories.tsx @@ -13,20 +13,20 @@ Default.args = {}; export const WithoutHeader = Template.bind({}); WithoutHeader.args = { - noHeader: true, + noHeader: true }; export const WithAgreeButton = Template.bind({}); WithAgreeButton.args = { - onAgreeTerms: () => alert('Agreed to Privacy Policy'), + onAgreeTerms: () => alert('Agreed to Privacy Policy') }; export const WithExtraStyles = Template.bind({}); WithExtraStyles.args = { - extraStyles: true, + extraStyles: true }; export const WithArrowBack = Template.bind({}); WithArrowBack.args = { - onArrowBack: () => alert('Arrow back clicked'), + onArrowBack: () => alert('Arrow back clicked') }; diff --git a/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx b/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx index 235a351a0..c3a671918 100644 --- a/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx +++ b/frontend/src/components/design-library/molecules/content/terms/terms-of-service/terms-of-service.stories.tsx @@ -15,21 +15,21 @@ Default.args = { export const WithArrowBack = Template.bind({}); WithArrowBack.args = { - onArrowBack: () => alert('Arrow back clicked'), + onArrowBack: () => alert('Arrow back clicked') }; export const WithAgreeButton = Template.bind({}); WithAgreeButton.args = { - onAgreeTerms: () => alert('Agreed to Terms of Service'), + onAgreeTerms: () => alert('Agreed to Terms of Service') }; export const WithBothActions = Template.bind({}); WithBothActions.args = { onArrowBack: () => alert('Arrow back clicked'), - onAgreeTerms: () => alert('Agreed to Terms of Service'), + onAgreeTerms: () => alert('Agreed to Terms of Service') }; export const WithoutExtraStyles = Template.bind({}); WithoutExtraStyles.args = { - extraStyles: false, + extraStyles: false }; \ No newline at end of file diff --git a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts index e7d0f4649..39532239e 100644 --- a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.styles.ts @@ -4,12 +4,12 @@ import { Toolbar, Typography } from '@mui/material' export const TopBarStyled = styled(Toolbar)(({ theme }) => ({ borderBottom: `1px solid ${theme.palette.divider}`, - marginBottom: theme.spacing(2), + marginBottom: theme.spacing(2) })) export const AppBarHeader = styled(Typography)(({ theme }) => ({ width: '100%', - color: theme.palette.common.white, + color: theme.palette.common.white })) export const AppBar = styled(MuiAppBar)({ diff --git a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx index a9ab16f31..1efbaea88 100644 --- a/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/bottom-section-dialog/bottom-section-dialog.tsx @@ -2,11 +2,11 @@ import React from 'react' import { Dialog, IconButton, - Slide, + Slide } from '@mui/material' import { - Close, + Close } from '@mui/icons-material' import { InfoList } from './CommonStyles' @@ -17,7 +17,7 @@ const Transition = React.forwardRef(function Transition( props: TransitionProps & { children: React.ReactElement; }, - ref: React.Ref, + ref: React.Ref ) { return ; }); @@ -27,7 +27,7 @@ const BottomSectionDialog = ({ open, onClose, title, - content, + content }) => { return ( @@ -36,19 +36,19 @@ const BottomSectionDialog = ({ open={ open } onClose={ onClose } slots={{ - transition: Transition, + transition: Transition }} > - + {title} diff --git a/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx b/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx index b3fbd4595..c1342bafc 100644 --- a/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx +++ b/frontend/src/components/design-library/molecules/dialogs/terms-dialog/terms-dialog.tsx @@ -1,7 +1,6 @@ import React from "react"; -import { Dialog, DialogContent, DialogTitle } from "@mui/material"; +import { Dialog, DialogContent } from "@mui/material"; import TermsOfService from "../../content/terms/terms-of-service/terms-of-service"; -import { FormattedMessage } from "react-intl"; const TermsDialog = ({ open, diff --git a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx index 5675d56aa..ecfe6a1c1 100644 --- a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx +++ b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-signup/login-form-signup.tsx @@ -366,7 +366,7 @@ const LoginFormSignup = ({ } - + diff --git a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx index b1f59eee0..acc502919 100644 --- a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx +++ b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.stories.tsx @@ -6,8 +6,8 @@ const meta: Meta = { title: 'Design Library/Molecules/Lists/VerticalMenuList', component: VerticalMenulList, parameters: { - layout: 'centered', - }, + layout: 'centered' + } } export default meta @@ -19,9 +19,9 @@ export const Default: Story = { items: [ { label: 'Dashboard', onClick: () => alert('Dashboard clicked') }, { label: 'Settings', onClick: () => alert('Settings clicked') }, - { label: 'Logout', onClick: () => alert('Logout clicked') }, - ], - }, + { label: 'Logout', onClick: () => alert('Logout clicked') } + ] + } } export const DialogType: Story = { @@ -31,7 +31,7 @@ export const DialogType: Story = { items: [ { label: 'Privacy Policy', component:
Privacy Policy Content
}, { label: 'Terms of Service', component:
Terms of Service Content
}, - { label: 'Cookie Policy', component:
Cookie Policy Content
}, - ], - }, + { label: 'Cookie Policy', component:
Cookie Policy Content
} + ] + } } diff --git a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts index fc4e69f43..1549ca363 100644 --- a/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts +++ b/frontend/src/components/design-library/molecules/lists/vertical-menu-list/vertical-menu-list.styles.ts @@ -2,15 +2,15 @@ import { styled } from '@mui/material/styles' import { List, ListItemButton, Typography } from '@mui/material' export const TitleStyled = styled(Typography)(({ theme }) => ({ - paddingLeft: theme.spacing(2), + paddingLeft: theme.spacing(2) })) export const ListStyled = styled(List)(({ theme }) => ({ marginLeft: theme.spacing(0), - paddingLeft: theme.spacing(0), + paddingLeft: theme.spacing(0) })) export const ListItemButtonStyled = styled(ListItemButton)(({ theme }) => ({ marginLeft: theme.spacing(0), - paddingLeft: theme.spacing(2), + paddingLeft: theme.spacing(2) })) \ No newline at end of file diff --git a/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx b/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx index cf334f06d..14d9a7785 100644 --- a/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx +++ b/frontend/src/components/design-library/organisms/layouts/bottom-bar-layouts/bottom-bar-layout/bottom-bar-layout.tsx @@ -4,7 +4,7 @@ import { useHistory } from 'react-router-dom' import { Grid, - Typography, + Typography } from '@mui/material' import SubscribeForm from '../../../forms/subscribe-forms/subscribe-form/subscribe-form' diff --git a/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx b/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx index b6f7ca03e..da92a48df 100644 --- a/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/pricing-public-page/pricing-public-page.tsx @@ -4,8 +4,6 @@ import { Button, Card, CardActions, CardContent, CardHeader, Grid, Typography } import { FormattedMessage } from 'react-intl' import { Layout, HeroContent, CardPricing } from './pricing-public-page.styles' -import MainTitle from 'design-library/atoms/typography/main-title/main-title' -import { HeroTitleStyled } from 'design-library/atoms/typography/hero-title/hero-title.styles' import HeroTitle from 'design-library/atoms/typography/hero-title/hero-title' interface Tier { diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx index 6dcd09c48..0ee1f4e05 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.stories.tsx @@ -15,12 +15,12 @@ export const Default: Story = {}; export const WithError: Story = { args: { - error: 'Unable to load session data', - }, + error: 'Unable to load session data' + } }; export const AlternateSession: Story = { args: { - sessionId: 'another-session-id', - }, + sessionId: 'another-session-id' + } }; diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx index ff0d39021..1e0e15966 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/forgot-password-page/forgot-password-page.tsx @@ -5,7 +5,7 @@ import LoginFormForgot from 'design-library/molecules/form-section/login-form/lo import { useHistory } from 'react-router-dom'; const ForgotUserPage = ({ - forgotPassword, + forgotPassword }) => { const history = useHistory() return ( diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx index e815cad88..731a72bac 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-page.tsx @@ -7,7 +7,7 @@ import { useHistory } from 'react-router-dom'; const ResetPasswordPage = ({ user, - resetPassword, + resetPassword }) => { const history = useHistory() const { data, completed } = user || {} diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx index e0d3716f8..2a823b872 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/reset-password-page/reset-password-public-page.stories.tsx @@ -19,8 +19,8 @@ export const Default: Story = { username: 'john_doe', email: 'john_doe@example.com' } - }, - }, + } + } }; export const Loading: Story = { @@ -29,17 +29,17 @@ export const Loading: Story = { completed: false, data: {} } - }, + } }; export const WithError: Story = { args: { - error: 'Unable to load session data', - }, + error: 'Unable to load session data' + } }; export const AlternateSession: Story = { args: { - sessionId: 'another-session-id', - }, + sessionId: 'another-session-id' + } }; diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx index 2451b3891..d6ccccdb0 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-page.tsx @@ -5,7 +5,7 @@ import { FormattedMessage } from 'react-intl'; import { useHistory } from 'react-router-dom'; const SigninPage = ({ - addNotification, + addNotification }) => { const history = useHistory(); return ( diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx index 04f46da21..e241568be 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signin-page/signin-public-page.stories.tsx @@ -15,12 +15,12 @@ export const Default: Story = {}; export const WithError: Story = { args: { - error: 'Unable to load session data', - }, + error: 'Unable to load session data' + } }; export const AlternateSession: Story = { args: { - sessionId: 'another-session-id', - }, + sessionId: 'another-session-id' + } }; \ No newline at end of file diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx index 3588768c3..a56fa8f6a 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-page.tsx @@ -7,7 +7,7 @@ import { useHistory } from 'react-router-dom'; const SignupPage = ({ handleSignup, roles, - fetchRoles, + fetchRoles }) => { const history = useHistory(); return ( diff --git a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx index c436252a9..46ada1f45 100644 --- a/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx +++ b/frontend/src/components/design-library/pages/public-pages/session-public-pages/signup-page/signup-public-page.stories.tsx @@ -22,18 +22,18 @@ export const Default: Story = { { name: 'sponsor', label: 'Sponsor' } ] }, - fetchRoles: () => {}, - }, + fetchRoles: () => {} + } }; export const WithError: Story = { args: { - error: 'Unable to load session data', - }, + error: 'Unable to load session data' + } }; export const AlternateSession: Story = { args: { - sessionId: 'another-session-id', - }, + sessionId: 'another-session-id' + } }; diff --git a/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx index 04e593f8d..1db90a6bf 100644 --- a/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx +++ b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.stories.tsx @@ -6,10 +6,10 @@ const meta: Meta = { title: 'Design Library/Templates/Base/SignupSigninBase', component: SignupSigninBase, parameters: { - layout: 'fullscreen', + layout: 'fullscreen' }, args: { - children:
Default Content
, + children:
Default Content
} }; export default meta; @@ -19,5 +19,5 @@ type Story = StoryObj; export const Default: Story = { args: { - }, + } }; \ No newline at end of file diff --git a/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts index 1be2ae5d7..437250bfd 100644 --- a/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts +++ b/frontend/src/components/design-library/templates/base/signup-signin-base/signup-signin-base.styles.ts @@ -38,7 +38,7 @@ export const CloudsLayer = styled('div')({ position: 'absolute', inset: 0, pointerEvents: 'none', - zIndex: 2, + zIndex: 2 }); export const Cloud = styled('div')< From b97dfc73de5856b82509dac6fe919972f2ec48a2 Mon Sep 17 00:00:00 2001 From: Alexandre Magno Date: Mon, 10 Nov 2025 12:44:47 +0100 Subject: [PATCH 19/19] route adjustments --- frontend/src/actions/loginActions.js | 4 ++-- .../login-form-reset/login-form-reset.tsx | 6 ++++-- frontend/src/main/routes.js | 13 ++++++++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/frontend/src/actions/loginActions.js b/frontend/src/actions/loginActions.js index 169783ec0..6d455e9d5 100644 --- a/frontend/src/actions/loginActions.js +++ b/frontend/src/actions/loginActions.js @@ -231,9 +231,9 @@ export const forgotPassword = data => { .post(api.API_URL + '/auth/forgot-password', data) .then(response => { if(response) { - dispatch(addNotification('user.forgot.password.successfull')) + return dispatch(addNotification('user.forgot.password.successfull')) } else { - dispatch(addNotification('user.forgot.password.error')) + return dispatch(addNotification('user.forgot.password.error')) } }) .catch(error => { diff --git a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-reset/login-form-reset.tsx b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-reset/login-form-reset.tsx index f9294c124..b9a33a15b 100644 --- a/frontend/src/components/design-library/molecules/form-section/login-form/login-form-reset/login-form-reset.tsx +++ b/frontend/src/components/design-library/molecules/form-section/login-form/login-form-reset/login-form-reset.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react' import { FormattedMessage } from 'react-intl' -import { useParams } from 'react-router-dom' +import { useHistory, useParams } from 'react-router-dom' import { Button, Typography @@ -17,7 +17,7 @@ type LoginFormResetProps = { action?: string onClose?: () => void onSignin?: () => void - onReset?: ({ password, token}:LoginOnResetProps) => void + onReset?: ({ password, token}:LoginOnResetProps) => Promise noCancelButton?: boolean } @@ -27,6 +27,7 @@ type ErrorStateType = { } const LoginFormReset = ({ action, noCancelButton, onClose, onSignin, onReset }:LoginFormResetProps) => { + const history = useHistory() const { token } = useParams<{ token: string }>() @@ -70,6 +71,7 @@ const LoginFormReset = ({ action, noCancelButton, onClose, onSignin, onReset }:L const password = event.target.password.value if(validForm) { await onReset({ password, token }) + history.push('/signin') } } diff --git a/frontend/src/main/routes.js b/frontend/src/main/routes.js index 9bee2a368..2509b89d9 100644 --- a/frontend/src/main/routes.js +++ b/frontend/src/main/routes.js @@ -27,7 +27,18 @@ export default props => ( : } /> - +

px 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�ifCd+02=hmLWjT`45WFse--#1`Y)D1c1LQ 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