diff --git a/public/assets/chevron-left.svg b/public/assets/chevron-left.svg new file mode 100644 index 0000000..85a5459 --- /dev/null +++ b/public/assets/chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/assets/unpinned.svg b/public/assets/unpinned.svg index 9653d1f..27e310a 100644 --- a/public/assets/unpinned.svg +++ b/public/assets/unpinned.svg @@ -1,5 +1,6 @@ - - - - + + + + \ No newline at end of file diff --git a/src/components/Dashboard/OperatorGrid/OperatorGrid.tsx b/src/components/Dashboard/OperatorGrid/OperatorGrid.tsx index ae25002..7122b15 100644 --- a/src/components/Dashboard/OperatorGrid/OperatorGrid.tsx +++ b/src/components/Dashboard/OperatorGrid/OperatorGrid.tsx @@ -1,5 +1,6 @@ import { breakpoints } from '@/configs/ui.configs' import styled from '@emotion/styled' +import Link from 'next/link' import React from 'react' interface Operator { @@ -15,57 +16,57 @@ interface OperatorGridProps {} const operators: Operator[] = [ { - id: '1234', + id: '1', image: '/dashboard/mock/operators/1.gif', - name: 'OP1234', + name: 'OP 1', pointsPerHour: 304, isStaked: false, isPinned: false, }, { - id: '1235', + id: '2', image: '/dashboard/mock/operators/2.gif', - name: 'OP1235', + name: 'OP 2', pointsPerHour: 304, isStaked: true, isPinned: false, }, { - id: '1236', + id: '3', image: '/dashboard/mock/operators/3.gif', - name: 'OP1236', + name: 'OP 3', pointsPerHour: 304, isStaked: true, isPinned: true, }, { - id: '1237', + id: '4', image: '/dashboard/mock/operators/4.gif', - name: 'OP1237', + name: 'OP 4', pointsPerHour: 304, isStaked: true, isPinned: false, }, { - id: '1238', + id: '5', image: '/dashboard/mock/operators/5.gif', - name: 'OP1238', + name: 'OP 5', pointsPerHour: 304, isStaked: true, isPinned: false, }, { - id: '1239', + id: '6', image: '/dashboard/mock/operators/6.gif', - name: 'OP1239', + name: 'OP 6', pointsPerHour: 304, isStaked: true, isPinned: false, }, { - id: '1240', + id: '7', image: '/dashboard/mock/operators/7.gif', - name: 'OP1240', + name: 'OP 7', pointsPerHour: 304, isStaked: true, isPinned: false, @@ -108,7 +109,9 @@ const OperatorGrid: React.FC = () => { {operators.map((operator) => ( - + + + {operator.name} @@ -190,7 +193,8 @@ const IconButton = styled.button` display: flex; align-items: center; justify-content: center; - border: 1px solid rgb(var(--lsd-border-primary)); + border: none; + border-left: 1px solid rgb(var(--lsd-border-primary)); cursor: pointer; height: 28px; ` @@ -230,6 +234,12 @@ const Grid = styled.div` const OperatorCard = styled.div` display: flex; flex-direction: column; + + color: rgb(var(--lsd-text-primary)); + + a { + display: flex; + } ` const OperatorImage = styled.img` @@ -251,13 +261,14 @@ const OperatorName = styled.div` const PointsPerHour = styled.div` display: flex; justify-content: space-between; - margin-top: 8px; align-items: center; ` const Actions = styled.div` display: flex; - padding: 16px 0; + align-items: center; + border: 1px solid rgb(var(--lsd-border-primary)); + border-radius: 0; ` const ActionButton = styled.button<{ isStaked: boolean }>` @@ -268,10 +279,7 @@ const ActionButton = styled.button<{ isStaked: boolean }>` props.isStaked ? 'rgb(var(--lsd-text-primary))' : 'rgb(var(--lsd-text-secondary))'}; - border: 1px solid rgb(var(--lsd-border-primary)); - border-right: none; - border-radius: 0; - + border: none; font-weight: 400; font-size: 12px; line-height: 16px; diff --git a/src/components/Dashboard/ProgressBar/ProgressBar.tsx b/src/components/Dashboard/ProgressBar/ProgressBar.tsx index a4f6408..f211f6a 100644 --- a/src/components/Dashboard/ProgressBar/ProgressBar.tsx +++ b/src/components/Dashboard/ProgressBar/ProgressBar.tsx @@ -62,7 +62,7 @@ const ProgressBar: React.FC = ({ - + {timeRemaining} @@ -162,7 +162,7 @@ const ProgressFooter = styled.div` ` const TimeRemaining = styled.div` - border: 1px solid #321504; + border: 1px solid var(--dark-orange); display: flex; align-items: center; gap: 16px; diff --git a/src/components/Explore/OperatorGrid/OperatorGrid.tsx b/src/components/Explore/OperatorGrid/OperatorGrid.tsx index 382089a..9ee7ec2 100644 --- a/src/components/Explore/OperatorGrid/OperatorGrid.tsx +++ b/src/components/Explore/OperatorGrid/OperatorGrid.tsx @@ -57,7 +57,10 @@ const OperatorGrid: React.FC = () => { return ( {operatorImages.map((operator, index) => ( - + = ({ + id, +}: OperatorDetailsProps) => { + const handleDownload = () => { + window.open(`/dashboard/mock/operators/${id % 7}.gif`, '_blank') + } + + const handleShare = async () => { + if (navigator.share) { + try { + await navigator.share({ + title: 'Logos Operator', + text: 'Check out this Logos Operator!', + url: window.location.href, + }) + } catch (error) { + console.error('Error sharing:', error) + } + } else { + alert('Web Share API is not supported in this browser.') + } + } + + return ( + + + {`Operator + + + + + + + Memetic + + Operator + #{id} + + + + Count + 3 + + + Body + Purple + + + + + Head + Woodsman + + + Eyes + Patch + + + Earing + None + + + + Archetype + Memetic + + + {operatorInfo.map((info, index) => ( + + {info.trait} + {info.value} + + ))} + + + + ) +} + +const Container = styled.section` + display: grid; + grid-template-columns: repeat(24, 1fr); + gap: 0 16px; + width: 100%; + + @media (max-width: ${breakpoints.md}px) { + grid-template-columns: repeat(1, 1fr); + margin-top: 40px; + } +` + +const OperatorImage = styled.div` + position: relative; + + img { + width: 100%; + height: auto; + } + + grid-column: 1 / 13; + + @media (max-width: ${breakpoints.md}px) { + grid-column: 1 / 2; + } +` + +const OperatorInfo = styled.div` + grid-column: 15 / 25; + + @media (max-width: ${breakpoints.md}px) { + grid-column: 1 / 2; + } +` + +const ActionButtons = styled.div` + display: flex; + gap: -1px; + margin-top: 16px; + + button:first-of-type { + border-right: none; + } +` + +const Button = styled.button` + flex: 1; + padding: 10px 40px; + border: 1px solid #fff; + background: transparent; + color: #fff; + font: 400 14px/1 Courier, sans-serif; + cursor: pointer; +` + +const OperatorTitle = styled.h1` + font-size: 32px; + font-weight: 400; + line-height: 40px; + margin: 0; +` + +const OperatorSubtitle = styled.div` + display: flex; + gap: 16px; + font-size: 18px; + margin-top: 16px; + + .id { + opacity: 0.5; + } +` + +const AttributesFirstGrid = styled.div` + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 2px; + margin-top: 24px; +` + +const AttributesSecondGrid = styled(AttributesFirstGrid)` + grid-template-columns: repeat(3, 1fr); + margin-top: 2px; +` + +const AttributeItem = styled.div` + background-color: var(--dark-orange); + padding: 16px 8px; +` + +const AttributeLabel = styled.div` + font-size: 14px; + color: var(--orange); +` + +const AttributeValue = styled.div` + margin-top: 8px; + font-size: 14px; + color: var(--orange); +` + +const ArchetypeSection = styled.div` + display: flex; + justify-content: space-between; + background-color: var(--grey-900); + padding: 16px 8px; + margin-top: 24px; +` + +const DetailsList = styled.div` + display: flex; + flex-direction: column; + gap: 2px; + margin-top: 24px; +` + +const DetailItem = styled.div` + display: flex; + justify-content: space-between; + background-color: var(--grey-900); + padding: 16px 8px; +` + +const DetailLabel = styled.span` + font-size: 14px; +` + +const DetailValue = styled.span` + font-size: 14px; +` + +export default OperatorDetails diff --git a/src/components/Operator/OperatorDetails/index.ts b/src/components/Operator/OperatorDetails/index.ts new file mode 100644 index 0000000..002b23f --- /dev/null +++ b/src/components/Operator/OperatorDetails/index.ts @@ -0,0 +1 @@ +export { default as OperatorDetails } from './OperatorDetails' diff --git a/src/components/Operator/SimilarOperators/SimilarOperators.tsx b/src/components/Operator/SimilarOperators/SimilarOperators.tsx new file mode 100644 index 0000000..0bbfb3e --- /dev/null +++ b/src/components/Operator/SimilarOperators/SimilarOperators.tsx @@ -0,0 +1,81 @@ +import styled from '@emotion/styled' +import Link from 'next/link' +import React from 'react' + +interface SimilarOperatorsProps {} + +const operators = [ + { + id: 1, + src: '/dashboard/mock/operators/1.gif', + }, + { + id: 2, + src: '/dashboard/mock/operators/2.gif', + }, + { + id: 3, + src: '/dashboard/mock/operators/3.gif', + }, + { + id: 4, + src: '/dashboard/mock/operators/4.gif', + }, + { + id: 5, + src: '/dashboard/mock/operators/5.gif', + }, + { + id: 6, + src: '/dashboard/mock/operators/6.gif', + }, +] + +const SimilarOperators: React.FC = () => { + return ( + + Similar Operators + + {operators.map((operator) => ( + + + + ))} + + + ) +} + +const Container = styled.section` + margin-top: 72px; + + @media (max-width: 991px) { + margin-top: 40px; + } +` + +const SectionTitle = styled.h2` + font-size: 28px; + margin: 0 0 24px 0; +` + +const OperatorGrid = styled.div` + display: grid; + grid-template-columns: repeat(4, 1fr); + + gap: 16px; +` + +// full width, aspect ratio 1 in grid +const OperatorImage = styled.img` + width: 100%; + aspect-ratio: 1; + object-fit: cover; + cursor: pointer; +` + +export default SimilarOperators diff --git a/src/components/Operator/SimilarOperators/index.ts b/src/components/Operator/SimilarOperators/index.ts new file mode 100644 index 0000000..1324217 --- /dev/null +++ b/src/components/Operator/SimilarOperators/index.ts @@ -0,0 +1 @@ +export { default as SimilarOperators } from './SimilarOperators' diff --git a/src/containers/Explore/ExploreContainer.tsx b/src/containers/Explore/ExploreContainer.tsx index 9a2021d..f333577 100644 --- a/src/containers/Explore/ExploreContainer.tsx +++ b/src/containers/Explore/ExploreContainer.tsx @@ -26,14 +26,6 @@ const StyledExploreSection = styled.main` line-height: 48px; margin-top: 60px; } - - @media (max-width: 991px) { - padding: 0 20px; - - .section-title { - margin-top: 40px; - } - } ` export default ExploreSection diff --git a/src/containers/Operator/OperatorContainer.tsx b/src/containers/Operator/OperatorContainer.tsx new file mode 100644 index 0000000..5217c70 --- /dev/null +++ b/src/containers/Operator/OperatorContainer.tsx @@ -0,0 +1,47 @@ +import { OperatorDetails } from '@/components/Operator/OperatorDetails' +import { SimilarOperators } from '@/components/Operator/SimilarOperators' +import styled from '@emotion/styled' +import { useRouter } from 'next/router' +import React from 'react' + +interface ExploreOperatorProps { + id: string +} + +const ExploreOperator: React.FC = ({ id }) => { + const router = useRouter() + + const handleGoBack = () => { + router.back() + } + return ( + + + Share icon + + + + + ) +} + +const Container = styled.div` + display: flex; + flex-direction: column; + overflow: hidden; +` + +const GoBackButton = styled.button` + display: flex; + align-items: center; + justify-content: center; + margin-top: 36px; + width: 28px; + height: 28px; + border: 1px solid rgba(var(--lsd-border-primary)); + background: transparent; + margin-bottom: 16px; + cursor: pointer; +` + +export default ExploreOperator diff --git a/src/containers/Operator/index.ts b/src/containers/Operator/index.ts new file mode 100644 index 0000000..c137422 --- /dev/null +++ b/src/containers/Operator/index.ts @@ -0,0 +1 @@ +export { default as OperatorContainer } from './OperatorContainer' diff --git a/src/layouts/OperatorInfoLayout/OperatorInfoLayout.layout.tsx b/src/layouts/OperatorInfoLayout/OperatorInfoLayout.layout.tsx new file mode 100644 index 0000000..069b86c --- /dev/null +++ b/src/layouts/OperatorInfoLayout/OperatorInfoLayout.layout.tsx @@ -0,0 +1,35 @@ +import { Footer } from '@/components/Footer' +import { Header } from '@/components/Header/Header' +import { breakpoints, uiConfigs } from '@/configs/ui.configs' +import styled from '@emotion/styled' +import React, { PropsWithChildren } from 'react' + +interface OperatorInfoLayoutProps {} + +const OperatorInfoLayout: React.FC = ( + props: PropsWithChildren, +) => { + return ( + +
+
{props.children}
+