Skip to content

Commit

Permalink
(launch) feat: add path page (#78)
Browse files Browse the repository at this point in the history
(launch) feat: add path page
  • Loading branch information
Tanya-atatakai authored Aug 21, 2024
1 parent a726a5d commit f425ced
Show file tree
Hide file tree
Showing 23 changed files with 689 additions and 152 deletions.
2 changes: 1 addition & 1 deletion apps/launch/common-util/constants/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export const URL = {
myStakingContracts: 'my-staking-contracts',
createContract: 'my-staking-contracts/create',
nominateContract: 'nominate-contract',
paths: 'paths',
path: 'path',
pageNotFound: 'page-not-found',
};
6 changes: 3 additions & 3 deletions apps/launch/components/Layout/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ const MenuInstance: FC<MenuInstanceProps> = ({ selectedMenu, handleMenuItemClick

const items: MenuItem[] = useMemo(
() => [
{ label: 'Path', key: 'path', path: `/path` },
{
label: 'My staking contracts',
key: URL.myStakingContracts,
path: `/${networkName}/${URL.myStakingContracts}`,
path: `/${networkName || 'ethereum'}/${URL.myStakingContracts}`,
},
{ label: 'Paths', key: 'paths', path: `/paths` },
{ label: 'Docs', key: 'docs', path: '/docs' },
],
[networkName],
Expand All @@ -54,7 +54,7 @@ const MenuInstance: FC<MenuInstanceProps> = ({ selectedMenu, handleMenuItemClick
handleMenuItemClick({
label: '',
key,
path: PAGES_TO_LOAD_WITH_CHAIN_ID.includes(key) ? `/${networkName}/${key}` : `/${key}`,
path: PAGES_TO_LOAD_WITH_CHAIN_ID.includes(key) ? `/${networkName || 'ethereum'}/${key}` : `/${key}`,
})
}
/>
Expand Down
96 changes: 96 additions & 0 deletions apps/launch/components/Path/StepContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon';
import { Button, Flex, Typography } from 'antd';
import styled from 'styled-components';

import { COLOR } from 'libs/ui-theme/src';

import { SetNextStep, SetPrevStep } from './types';

const { Text, Title } = Typography;

const IconContainer = styled.div`
display: flex;
width: max-content;
padding: 8px;
border-radius: 6px;
background: ${COLOR.PRIMARY_BG};
`;

const StyledUl = styled.ul`
list-style-type: square;
margin: 0;
padding-left: 24px;
li {
padding-left: 8px;
&::marker {
color: #b972e8;
}
}
`;

type StepIconProps = {
icon: React.ForwardRefExoticComponent<
Omit<AntdIconProps, 'ref'> & React.RefAttributes<HTMLSpanElement>
>;
};

const StepIcon = ({ icon: Icon }: StepIconProps) => (
<IconContainer>
<Icon style={{ color: COLOR.PRIMARY, fontSize: 24 }} />
</IconContainer>
);


type StepListProps = {
title: string;
items: (string | React.ReactNode)[];
};

export const StepList = ({ title, items }: StepListProps) => (
<Flex vertical gap={12}>
<Text>{title}</Text>
<StyledUl>
{items.map((item, index) => (
<li key={index}>
<Text type="secondary">{item}</Text>
</li>
))}
</StyledUl>
</Flex>
);

type StepContentProps = {
icon: StepIconProps['icon'];
title: string;
children: React.ReactNode;
onPrev: SetPrevStep;
onNext: SetNextStep;
isLast?: boolean;
};

export const StepContent = ({
icon,
title,
children,
onPrev,
onNext,
isLast,
}: StepContentProps) => (
<Flex vertical gap={16}>
<StepIcon icon={icon} />
<Title level={4} className="m-0">
{title}
</Title>
{children}
<Flex justify="end" gap={12} className="mt-24">
<Button size="large" onClick={onPrev}>
Prev step
</Button>
{!isLast && (
<Button type="primary" size="large" onClick={onNext}>
Next step
</Button>
)}
</Flex>
</Flex>
);
15 changes: 15 additions & 0 deletions apps/launch/components/Path/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Define } from './steps/Define';
import { Design } from './steps/Design';
import { Engage } from './steps/Engage';
import { Intro } from './steps/Intro';
import { Promote } from './steps/Promote';
import { Watch } from './steps/Watch';

export const steps = [
{ title: 'Intro', content: Intro },
{ title: 'Define goals and KPIs', content: Define },
{ title: 'Design agent economy', content: Design },
{ title: 'Engage Builders', content: Engage },
{ title: 'Promote, co-market & observe', content: Promote },
{ title: 'Watch your metrics grow', content: Watch },
];
63 changes: 63 additions & 0 deletions apps/launch/components/Path/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Card, Flex, Steps } from 'antd';
import { useState } from 'react';
import styled from 'styled-components';

import { BREAK_POINT } from 'libs/ui-theme/src';

import { steps } from './constants';
import { SetNextStep, SetPrevStep, StepComponentProps } from './types';

const StyledMain = styled.main`
display: flex;
flex-direction: column;
max-width: ${BREAK_POINT.xl};
margin: 0 auto;
.ant-steps.ant-steps-vertical > .ant-steps-item:not(:last-child) .ant-steps-item-content {
min-height: 58px;
}
`;

const STEP_CONTENT_STYLE = { maxWidth: '720px', width: '100%' };
const LAST_STEP_KEY = 'path_last_step';

const renderStep = (
StepComponent: React.ComponentType<StepComponentProps>,
setPrevStep: SetPrevStep,
setNextStep: SetNextStep,
isLastStep: boolean,
) => <StepComponent onPrev={setPrevStep} onNext={setNextStep} isLastStep={isLastStep} />;

export const PathPage = () => {
const [step, setStep] = useState(Number(sessionStorage.getItem(LAST_STEP_KEY) || '0'));

const isLastStep = step === steps.length - 1;

const onChangeStep = (value: number) => {
setStep(value);
sessionStorage.setItem(LAST_STEP_KEY, value.toString());
};

const setPrevStep = () => {
const prevStep = step === 0 ? step : step - 1;
onChangeStep(prevStep);
};

const setNextStep = () => {
const nextStep = isLastStep ? 0 : step + 1;
onChangeStep(nextStep);
};

return (
<StyledMain>
<Flex gap={24} align="start">
<Card>
<Steps direction="vertical" current={step} items={steps} onChange={onChangeStep} />
</Card>
<Card style={STEP_CONTENT_STYLE}>
{renderStep(steps[step].content, setPrevStep, setNextStep, isLastStep)}
</Card>
</Flex>
</StyledMain>
);
};
36 changes: 36 additions & 0 deletions apps/launch/components/Path/steps/Define.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { EditOutlined } from '@ant-design/icons';
import { Divider } from 'antd';

import { StepContent, StepList } from '../StepContent';
import { StepComponentProps } from '../types';

const createDocData = {
title: 'Create a short document that touches on the use case and market need.',
items: [
'What are the goals you have for your chain ecosystem and the KPIs you are trying to hit?',
'What is the market need for autonomous AI agents in your ecosystem?',
'What is the use case that can satisfy this need?',
],
};

const defineKPIsData = {
title: 'Define KPIs & Goals.',
items: [
'What are the goals for the agents and what KPIs will define success?',
'What are the goals and KPIs of the agent economy?',
],
};

export const Define = ({ onPrev, onNext, isLastStep }: StepComponentProps) => (
<StepContent
icon={EditOutlined}
title="Define your goals and KPIs"
onPrev={onPrev}
onNext={onNext}
isLast={isLastStep}
>
<StepList title={createDocData.title} items={createDocData.items} />
<Divider className="m-0" />
<StepList title={defineKPIsData.title} items={defineKPIsData.items} />
</StepContent>
);
37 changes: 37 additions & 0 deletions apps/launch/components/Path/steps/Design.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { FileDoneOutlined } from '@ant-design/icons';

import { StepContent, StepList } from '../StepContent';
import { StepComponentProps } from '../types';

const putTogetherData = {
title:
'Put together a technical document that specifies how each agent in your economy will be designed, architected and how they interact with one another.',
items: [
'What do you want the individual agents to do?',
'How many agent instances of each type are required?',
// TODO: uncomment once it's clear what the link should be
// <>
// Translate KPI definitions in a staking contract specification. See the{' '}
// <a
// href="https://github.com/valory-xyz/autonolas-aip/blob/aip-2/docs/OlasAutomate.pdf"
// target="_blank"
// rel="noopener noreferrer"
// >
// Olas Predict Specification Document {UNICODE_SYMBOLS.EXTERNAL_LINK}
// </a>{' '}
// example.
// </>,
],
};

export const Design = ({ onPrev, onNext, isLastStep }: StepComponentProps) => (
<StepContent
icon={FileDoneOutlined}
title="Design and specify your agent economy"
onPrev={onPrev}
onNext={onNext}
isLast={isLastStep}
>
<StepList title={putTogetherData.title} items={putTogetherData.items} />
</StepContent>
);
67 changes: 67 additions & 0 deletions apps/launch/components/Path/steps/Engage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { CodeOutlined } from '@ant-design/icons';
import { Divider, Typography } from 'antd';
import Link from 'next/link';

import { UNICODE_SYMBOLS } from 'libs/util-constants/src';

import { URL } from 'common-util/constants/urls';
import { useAppSelector } from 'store/index';

import { StepContent, StepList } from '../StepContent';
import { StepComponentProps } from '../types';

const { Text } = Typography;

const developData = {
title: 'Develop your agent services.',
items: [
<>
Develop it yourself using the{' '}
<a href="https://docs.autonolas.network" target="_blank" rel="noopener noreferrer">
docs {UNICODE_SYMBOLS.EXTERNAL_LINK}
</a>
.
</>,
<>
Develop it yourself by attending the academy -{' '}
<a href="https://www.valory.xyz/academy" target="_blank" rel="noopener noreferrer">
sign up {UNICODE_SYMBOLS.EXTERNAL_LINK}
</a>
.
</>,
<>
Get matched with a qualified Builder -{' '}
<a href="mailto:[email protected]" target="_blank" rel="noopener noreferrer">
enquire {UNICODE_SYMBOLS.EXTERNAL_LINK}
</a>
.
</>,
],
};

export const Engage = ({ onPrev, onNext, isLastStep }: StepComponentProps) => {
const { networkName } = useAppSelector((state) => state.network);

return (
<StepContent
icon={CodeOutlined}
title="Engage Builders to architect & develop the agents"
onPrev={onPrev}
onNext={onNext}
isLast={isLastStep}
>
<StepList title={developData.title} items={developData.items} />
<Divider className="m-0" />
<Text>
<Link href={`/${networkName || 'ethereum'}/${URL.myStakingContracts}`}>
Create the Olas staking contract{' '}
</Link>{' '}
and embed the KPIs for autonomous AI agents to hit.
</Text>
<Divider className="m-0" />
<Text>Test the agent economy.</Text>
<Divider className="m-0" />
<Text>Deploy the staking contracts.</Text>
</StepContent>
);
};
23 changes: 23 additions & 0 deletions apps/launch/components/Path/steps/Intro.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Button, Flex, Typography } from 'antd';
import Image from 'next/image';

import { SetNextStep } from '../types';

const { Title, Paragraph } = Typography;

export const Intro = ({ onNext }: { onNext: SetNextStep }) => (
<Flex vertical align="center" gap={16}>
<Image src={`/images/path/intro.svg`} alt="Intro" width={672} height={192} />
<Title level={3} className="mb-0 mt-16">
Launch your own agent economy with Olas
</Title>
<Paragraph type="secondary" className="mb-0">
Create and deploy entire AI agent economies within your ecosystem efficiently. Here is a
comprehensive step by step guide that will help you the entire agent economy as an Olas
Launcher.
</Paragraph>
<Button type="primary" size="large" onClick={onNext}>
View path
</Button>
</Flex>
);
Loading

0 comments on commit f425ced

Please sign in to comment.