diff --git a/package.json b/package.json index b8e5d33..04fe5ce 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,9 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", - "@mui/icons-material": "^6.4.5", - "@mui/material": "^6.4.5", + "@mui/icons-material": "^6.4.11", + "@mui/material": "^6.4.11", + "@mui/system": "^7.0.2", "next": "15.1.7", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ab1051..3cf2cba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,11 +15,14 @@ importers: specifier: ^11.14.0 version: 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0) '@mui/icons-material': - specifier: ^6.4.5 + specifier: ^6.4.11 version: 6.4.11(@mui/material@6.4.11(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.2)(react@19.1.0) '@mui/material': - specifier: ^6.4.5 + specifier: ^6.4.11 version: 6.4.11(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@mui/system': + specifier: ^7.0.2 + version: 7.0.2(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0) next: specifier: 15.1.7 version: 15.1.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -414,6 +417,16 @@ packages: '@types/react': optional: true + '@mui/private-theming@7.0.2': + resolution: {integrity: sha512-6lt8heDC9wN8YaRqEdhqnm0cFCv08AMf4IlttFvOVn7ZdKd81PNpD/rEtPGLLwQAFyyKSxBG4/2XCgpbcdNKiA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@mui/styled-engine@6.4.11': resolution: {integrity: sha512-74AUmlHXaGNbyUqdK/+NwDJOZqgRQw6BcNvhoWYLq3LGbLTkE+khaJ7soz6cIabE4CPYqO2/QAIU1Z/HEjjpcw==} engines: {node: '>=14.0.0'} @@ -427,6 +440,19 @@ packages: '@emotion/styled': optional: true + '@mui/styled-engine@7.0.2': + resolution: {integrity: sha512-11Bt4YdHGlh7sB8P75S9mRCUxTlgv7HGbr0UKz6m6Z9KLeiw1Bm9y/t3iqLLVMvSHYB6zL8X8X+LmfTE++gyBw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@mui/system@6.4.11': resolution: {integrity: sha512-gibtsrZEwnDaT5+I/KloOj/yHluX5G8heknuxBpQOdEQ3Gc0avjSImn5hSeKp8D4thiwZiApuggIjZw1dQguUA==} engines: {node: '>=14.0.0'} @@ -443,6 +469,22 @@ packages: '@types/react': optional: true + '@mui/system@7.0.2': + resolution: {integrity: sha512-yFUraAWYWuKIISPPEVPSQ1NLeqmTT4qiQ+ktmyS8LO/KwHxB+NNVOacEZaIofh5x1NxY8rzphvU5X2heRZ/RDA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + '@mui/types@7.2.24': resolution: {integrity: sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==} peerDependencies: @@ -451,6 +493,14 @@ packages: '@types/react': optional: true + '@mui/types@7.4.1': + resolution: {integrity: sha512-gUL8IIAI52CRXP/MixT1tJKt3SI6tVv4U/9soFsTtAsHzaJQptZ42ffdHZV3niX1ei0aUgMvOxBBN0KYqdG39g==} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@mui/utils@6.4.9': resolution: {integrity: sha512-Y12Q9hbK9g+ZY0T3Rxrx9m2m10gaphDuUMgWxyV5kNJevVxXYCLclYUCC9vXaIk1/NdNDTcW2Yfr2OGvNFNmHg==} engines: {node: '>=14.0.0'} @@ -461,6 +511,16 @@ packages: '@types/react': optional: true + '@mui/utils@7.0.2': + resolution: {integrity: sha512-72gcuQjPzhj/MLmPHLCgZjy2VjOH4KniR/4qRtXTTXIEwbkgcN+Y5W/rC90rWtMmZbjt9svZev/z+QHUI4j74w==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@napi-rs/wasm-runtime@0.2.8': resolution: {integrity: sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==} @@ -2262,6 +2322,15 @@ snapshots: optionalDependencies: '@types/react': 19.1.2 + '@mui/private-theming@7.0.2(@types/react@19.1.2)(react@19.1.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@mui/utils': 7.0.2(@types/react@19.1.2)(react@19.1.0) + prop-types: 15.8.1 + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.2 + '@mui/styled-engine@6.4.11(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(react@19.1.0)': dependencies: '@babel/runtime': 7.27.0 @@ -2275,6 +2344,19 @@ snapshots: '@emotion/react': 11.14.0(@types/react@19.1.2)(react@19.1.0) '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0) + '@mui/styled-engine@7.0.2(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(react@19.1.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/sheet': 1.4.0 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 19.1.0 + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.1.2)(react@19.1.0) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0) + '@mui/system@6.4.11(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.0 @@ -2291,10 +2373,32 @@ snapshots: '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0) '@types/react': 19.1.2 + '@mui/system@7.0.2(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@mui/private-theming': 7.0.2(@types/react@19.1.2)(react@19.1.0) + '@mui/styled-engine': 7.0.2(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0))(react@19.1.0) + '@mui/types': 7.4.1(@types/react@19.1.2) + '@mui/utils': 7.0.2(@types/react@19.1.2)(react@19.1.0) + clsx: 2.1.1 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 19.1.0 + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@19.1.2)(react@19.1.0) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.2)(react@19.1.0))(@types/react@19.1.2)(react@19.1.0) + '@types/react': 19.1.2 + '@mui/types@7.2.24(@types/react@19.1.2)': optionalDependencies: '@types/react': 19.1.2 + '@mui/types@7.4.1(@types/react@19.1.2)': + dependencies: + '@babel/runtime': 7.27.0 + optionalDependencies: + '@types/react': 19.1.2 + '@mui/utils@6.4.9(@types/react@19.1.2)(react@19.1.0)': dependencies: '@babel/runtime': 7.27.0 @@ -2307,6 +2411,18 @@ snapshots: optionalDependencies: '@types/react': 19.1.2 + '@mui/utils@7.0.2(@types/react@19.1.2)(react@19.1.0)': + dependencies: + '@babel/runtime': 7.27.0 + '@mui/types': 7.4.1(@types/react@19.1.2) + '@types/prop-types': 15.7.14 + clsx: 2.1.1 + prop-types: 15.8.1 + react: 19.1.0 + react-is: 19.1.0 + optionalDependencies: + '@types/react': 19.1.2 + '@napi-rs/wasm-runtime@0.2.8': dependencies: '@emnapi/core': 1.4.1 diff --git a/public/google.svg b/public/google.svg new file mode 100644 index 0000000..a23b76f --- /dev/null +++ b/public/google.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/public/invalid-name.svg b/public/invalid-name.svg new file mode 100644 index 0000000..c8479cc --- /dev/null +++ b/public/invalid-name.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..ff86338 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,20 @@ + + + DispatchAI备份 2 + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/landing/components/TestimonialCard.tsx b/src/app/landing/components/TestimonialCard.tsx new file mode 100644 index 0000000..a5f73c1 --- /dev/null +++ b/src/app/landing/components/TestimonialCard.tsx @@ -0,0 +1,106 @@ +'use client'; + +import React from 'react'; +import styled from 'styled-components'; +import Image from 'next/image'; + +interface TestimonialCardProps { + quote: string; + name: string; + title: string; + sx?: React.CSSProperties; +} + +// Card container +const StyledCard = styled.div` + width: 100%; + max-width: 696px; + height: auto; + padding: 40px 24px; + border-radius: 24px; + border: 1px solid #d5d5d5; + background-color: #fff; + box-shadow: none; + flex-shrink: 0; + box-sizing: border-box; + + @media (min-width: 768px) { + padding: 60px; + } +`; + +// Quote icon +const QuoteIconBox = styled.div` + width: 22px; + height: 20px; + margin: 0 auto 24px 0; + + @media (min-width: 768px) { + margin: 0 554px 24px 0; + } +`; + +// Quote text +const QuoteText = styled.p` + font-family: Roboto, sans-serif; + font-size: 20px; + font-weight: bold; + line-height: 1.33; + color: #060606; + margin: 24px 0 48px; + text-align: left; + + @media (min-width: 768px) { + font-size: 24px; + width: 576px; + } +`; + +// Name text +const NameText = styled.p` + font-family: Roboto, sans-serif; + font-size: 20px; + font-weight: bold; + line-height: 1.25; + color: #060606; + margin-bottom: 16px; + + @media (min-width: 768px) { + font-size: 24px; + } +`; + +// Title text +const TitleText = styled.p` + font-family: Roboto, sans-serif; + font-size: 14px; + font-weight: 400; + line-height: 1.25; + color: #6d6d6d; + + @media (min-width: 768px) { + font-size: 16px; + } +`; + +export default function TestimonialCard({ quote, name, title, sx }: TestimonialCardProps) { + return ( + + + Quote Icon + + {quote} + {name} + {title} + + ); +} \ No newline at end of file diff --git a/src/app/landing/components/TestimonialsSection.tsx b/src/app/landing/components/TestimonialsSection.tsx new file mode 100644 index 0000000..c2a3473 --- /dev/null +++ b/src/app/landing/components/TestimonialsSection.tsx @@ -0,0 +1,83 @@ +'use client'; + +import styled from 'styled-components'; +import TestimonialCard from '@/app/landing/components/TestimonialCard'; + +interface Testimonial { + name: string; + title: string; + quote: string; + margin: React.CSSProperties; +} + +const testimonials: Testimonial[] = [ + { + quote: 'SmartAgent cut our missed calls by 80%. Lifesaver for my plumbing business!', + name: 'Josn', + title: 'CEO of ABC Company', + margin: { margin: '32px 16px' }, + }, + { + quote: 'Automated follow-ups saved me 10+ hours a week managing rentals.', + name: 'Jena', + title: 'Rental Manager', + margin: { margin: '32px 16px' }, + }, +]; + +// Section wrapper +const Wrapper = styled.section` + padding: 80px 16px; + background-color: white; +`; + +// Section title +const Title = styled.h2` + font-family: Roboto, sans-serif; + font-size: 36px; + font-weight: 900; + line-height: 1.25; + text-align: center; + color: #060606; + max-width: 864px; + margin: 120px auto 48px; + + @media (min-width: 768px) { + font-size: 48px; + margin: 200px auto 72px; + } +`; + +// Card layout container +const CardContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + gap: 24px; + + @media (min-width: 768px) { + flex-direction: row; + justify-content: center; + gap: 0; + overflow-x: auto; + } +`; + +export default function TestimonialsSection() { + return ( + + Trusted by Small Businesses Like Yours + + {testimonials.map((item, idx) => ( + + ))} + + + ); +}