Skip to content

Commit

Permalink
Merge pull request #223 from open-sauced/feat/landing-for-students
Browse files Browse the repository at this point in the history
feat: `/students` marketing page
  • Loading branch information
isabensusan authored Mar 22, 2024
2 parents 441123c + f39f77d commit cfe1887
Show file tree
Hide file tree
Showing 11 changed files with 578 additions and 10 deletions.
97 changes: 97 additions & 0 deletions components/sections/home-page/features/StudentsFeatures.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { SanityStudentsPage } from "../../../../types/schema";
import { Heading } from '../../../common/text'
import ContainerWithLine from '../../../common/ContainerWithLine'
import { motion } from 'framer-motion'
import { useInView } from 'react-intersection-observer'
import type { SanityImageAsset, SanityImageCrop, SanityImageHotspot, SanityReference } from "sanity-codegen";

import EndingLine from "../../../common/EndingLine";
import SectionWrapper from "../../../common/layout/SectionWrapper";

type TeamsFeaturesProps = {
features: SanityStudentsPage['features'];
};

export default function StudentsFeatures({ features } : TeamsFeaturesProps) {
return (
<SectionWrapper pbs={0}>
{ features!.map((feature) => <StudentFeature feature={feature!} />) }
<EndingLine />
</SectionWrapper>
);
}

function StudentFeature({ feature } : { feature : {
title?: string,
heading?: string,
description?: string,
image?: {
_type: 'image'
asset: SanityReference<SanityImageAsset>
crop?: SanityImageCrop
hotspot?: SanityImageHotspot
}
}}) {
const { title, heading, description, image } = feature!;
const [ refIcon, iconInView ] = useInView();

// text animation
const initPosY = 5;
const posY = iconInView ? 0 : initPosY;

return (
<ContainerWithLine>
<div className="pb-14 largeTablet:mb-32">
<div className="flex gap-y-24 py-10 flex-col-reverse largeTablet:flex-col">
<div ref={refIcon} className=" flex flex-col px-6 gap-y-12">
<div className="relative max-w-[650px]">
<motion.img
initial={{ opacity: 0, scale: 0.2 }}
animate={{ opacity: iconInView ? 1 : 0, scale: iconInView ? 1 : 0.5 }}
transition={{ duration: 0.5, delay: 0.1, ease: 'easeInOut' }}
className="absolute -left-[56px] largeTablet:-left-[77px] -top-[8px] largeTablet:-top-[4px]"
src={'/icons/find_icon.svg'}
alt="Find"
/>

<motion.div
initial={{ opacity: 0, y: initPosY, x: -10 }}
animate={{ opacity: iconInView ? 1 : 0, y: posY, x: iconInView ? 0 : -10 }}
transition={{ duration: 0.7, delay: 0.2, ease: 'easeInOut' }}
>
<div className="flex flex-col gap-4">
<p className="w-fit text-base px-3 py-1 text-darkOrange border border-darkOrange rounded-full">
{title}
</p>
<Heading component="h2" alignLarge="left">
{heading}
</Heading>
</div>
</motion.div>
</div>

<div className="">
<motion.div
initial={{ opacity: 0, y: initPosY, x: 10 }}
animate={{ opacity: iconInView ? 1 : 0, y: posY, x: iconInView ? 0 : 10 }}
transition={{ duration: 0.7, delay: 0.2, ease: 'easeInOut' }}
>
<p className="text-start font-light max-w-2xl text-lg text-neutral-300">
{description}
</p>
</motion.div>
</div>

<motion.div
initial={{ opacity: 0, y: initPosY, x: 10 }}
animate={{ opacity: iconInView ? 1 : 0, y: posY, x: iconInView ? 0 : 10 }}
transition={{ duration: 0.7, delay: 0.2, ease: 'easeInOut' }}
>
<img src={image as unknown as string} />
</motion.div>
</div>
</div>
</div>
</ContainerWithLine>
);
}
5 changes: 1 addition & 4 deletions components/sections/home-page/features/TeamsFeatures.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SanityTeamsPage } from "../../../../types/schema";
import { Heading, Typography } from '../../../common/text'
import { Heading } from '../../../common/text'
import ContainerWithLine from '../../../common/ContainerWithLine'
import { motion } from 'framer-motion'
import { useInView } from 'react-intersection-observer'
Expand All @@ -8,7 +8,6 @@ import type { SanityImageAsset, SanityImageCrop, SanityImageHotspot, SanityRefer
import EndingLine from "../../../common/EndingLine";
import SectionWrapper from "../../../common/layout/SectionWrapper";
import DecoratedText from "../../../common/text/utils/DecoratedText";
import Feature from "./Feature";

type TeamsFeaturesProps = {
topUseCase: SanityTeamsPage['topUseCase'];
Expand All @@ -28,7 +27,6 @@ export default function TeamsFeatures({ topUseCase, features } : TeamsFeaturesPr
function TopUseCase({ topUseCase } : { topUseCase: SanityTeamsPage['topUseCase']}) {
const { heading, image, subsections } = topUseCase!;
const [ refIcon, iconInView ] = useInView();
const [ refImage, imageInView ] = useInView();

// text animation
const initPosY = 5;
Expand Down Expand Up @@ -108,7 +106,6 @@ function TeamFeature({ feature } : { feature : {
}}) {
const { title, heading, description, image } = feature!;
const [ refIcon, iconInView ] = useInView();
const [ refImage, imageInView ] = useInView();

// text animation
const initPosY = 5;
Expand Down
13 changes: 9 additions & 4 deletions components/sections/navigation/DesktopNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ const useCases = [
title: 'Maintainers',
description: 'Grow and celebrate your open source community.',
},
{
link: '/contributors',
title: 'Contributors',
description: 'Start the path to your next contribution.',
{
link: "/contributors",
title: "Contributors",
description: "Start the path to your next contribution."
},
{
link: "/students",
title: "Students",
description: "Follow your passion and make your mark."
}
]

const DesktopNavigation: FC<DesktopNavigationProps> = ({
Expand Down
2 changes: 1 addition & 1 deletion components/sections/navigation/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const DropdownMenu = ({ menuItems, className, label }: DropdownMenuProps) => {
<Menu.Button className="text-white" aria-label={label}>
<Image src={open ? MobileCloseMenu : MobileMenu} alt="Menu" />
</Menu.Button>

<Menu.Items className="absolute z-50 h-fit min-h-[470px] right-6 left-6 mt-6 bg-gradient-to-r from-[#ED5432] to-[#EDA232] py-9 px-7 rounded-lg">
<p className="font-bold text-textPrimary text-xs opacity-70 tracking-[0.2em] pb-8">
MENU
Expand Down
1 change: 1 addition & 0 deletions components/sections/navigation/MobileNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const useCases = [
{ label: "Teams", url: "/teams" },
{ label: "Maintainers", url: "/maintainers" },
{ label: "Contributors", url: "/contributors" },
{ label: "Students", url: "/students" },
]

const MobileNavigation: FC<MobileNavigationProps> = ({
Expand Down
26 changes: 26 additions & 0 deletions lib/sanity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,32 @@ export const getTeamsPageData: () => Promise<SanityTeamsPage> = async () => {
return teamsPageData;
}

export const getStudentsPageData: () => Promise<SanityTeamsPage> = async () => {
const teamsPageData = await client.fetch(
`
*[_type == "studentsPage"][0] {
...,
hero {
...,
"image": image.asset->url,
users[] {
...,
"name": *[ _type == "user" && _id == ^._ref][0].name,
"website": *[ _type == "user" && _id == ^._ref][0].website,
"logo": *[ _type == "user" && _id == ^._ref][0].logo.asset->url,
}
},
features[] {
...,
"image": image.asset->url,
},
}
`
);
console.log('fetch', { teamsPageData });
return teamsPageData;
}

export const getSEOData: () => Promise<SanitySeo> = async () => {
const seoData = await client.fetch(
`
Expand Down
72 changes: 72 additions & 0 deletions pages/students/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { FC } from 'react'
import PageLayout from '../../components/common/layout/PageLayout'
import { getAllBlogs, getCommonData, getFeaturedBlogs, getStudentsPageData } from '../../lib/sanity'
import Background from '../../components/sections/about/Background'
import { SanityBlog, SanityFooter, SanityNavigation, SanitySeo, SanityStudentsPage, SanityUser } from '../../types/schema'
import Blogs from '../../components/sections/home-page/blogs/Blogs'
import Hero from '../../components/sections/home-page/Hero'
import Logos from '../../components/sections/home-page/Logos'
import CTA from '../../components/sections/teams/CTA'
import StudentsFeatures from "../../components/sections/home-page/features/StudentsFeatures";

interface Props {
data: {
commonData: {
navigationLinks: SanityNavigation[]
seoData: SanitySeo
footer: SanityFooter[]
}
studentsPageData: SanityStudentsPage
blogs: SanityBlog[]
featuredBlogs: SanityBlog[]
}
}

export async function getStaticProps() {
const [commonData, studentsPageData, featuredBlogs, blogs] = await Promise.all([
getCommonData(),
getStudentsPageData(),
getFeaturedBlogs(),
getAllBlogs(),
])

const data = { commonData, studentsPageData, featuredBlogs, blogs }

return {
props: {
data,
},
revalidate: 30,
}
}

const Index: FC<Props> = ({
data: { commonData, studentsPageData, blogs, featuredBlogs },
}) => {
const displayBlogs = [...blogs, ...featuredBlogs].sort(
(a, b) => +new Date(b._createdAt) - +new Date(a._createdAt)
)

return (
<PageLayout
seoData={commonData.seoData}
navigationURLs={commonData.navigationLinks}
BackgroundWrapper={Background}
>
<Hero data={studentsPageData.hero as unknown as SanityStudentsPage['hero']} />
<Logos data={studentsPageData.hero?.users as unknown as SanityUser[] || []} />
<StudentsFeatures features={studentsPageData.features} />
<CTA data={studentsPageData.ctaSection} />
<Blogs
data={{
_type: "blogSection",
title: "Our secret sauce",
heading: "$yellow-to-orange OpenSauced$yellow-to-orange Blog",
description: "Musings on the open-source community, engineering, and the future of talent acquisition."
}}
blogs={displayBlogs.slice(0, 4)} />
</PageLayout>
)
}

export default Index;
12 changes: 11 additions & 1 deletion sanity/deskStructure.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// /deskStructure.js
import S from '@sanity/desk-tool/structure-builder'
import { FaMoneyCheckAlt, FaInfoCircle, FaHome } from 'react-icons/fa'
import { FaMoneyCheckAlt, FaInfoCircle, FaHome, FaGraduationCap } from 'react-icons/fa'
import { VscOrganization } from "react-icons/vsc";

export default () =>
Expand Down Expand Up @@ -31,6 +31,16 @@ export default () =>
.title("Teams Page")
),

S.listItem()
.title("Students Page")
.icon(FaGraduationCap)
.child(
S.document()
.schemaType("studentsPage")
.documentId("studentsPage")
.title("Students Page")
),

S.listItem()
.title("Pricing Page")
.icon(FaMoneyCheckAlt)
Expand Down
Loading

0 comments on commit cfe1887

Please sign in to comment.