diff --git a/README.md b/README.md index e5d4784..5f4d6c6 100644 --- a/README.md +++ b/README.md @@ -65,13 +65,13 @@ Then set these variables in `.env.local`: - `NEXT_PUBLIC_SANITY_PROJECT_ID` should be the `projectId` value from [`sanity.json`]. - `NEXT_PUBLIC_SANITY_DATASET` should be the `dataset` value from [`sanity.json`]. - `SANITY_API_READ_TOKEN` create an API token with `read-only` permissions: - - Run this to open your project settings or go to https://manage.sanity.io/ and open your project: - ```bash - (cd studio && npx @sanity/cli manage) - ``` - - Go to **API** and the **Tokens** section at the bottom, launch its **Add API token** button. - - Name it `SANITY_API_READ_TOKEN`, set **Permissions** to `Viewer`. - - Hit **Save** and you can copy/paste the token. + - Run this to open your project settings or go to https://manage.sanity.io/ and open your project: + ```bash + (cd studio && npx @sanity/cli manage) + ``` + - Go to **API** and the **Tokens** section at the bottom, launch its **Add API token** button. + - Name it `SANITY_API_READ_TOKEN`, set **Permissions** to `Viewer`. + - Hit **Save** and you can copy/paste the token. Your `.env.local` file should look like this: diff --git a/components/Community/community.tsx b/components/Community/community.tsx new file mode 100644 index 0000000..8922b83 --- /dev/null +++ b/components/Community/community.tsx @@ -0,0 +1,34 @@ +import Image from 'next/image'; +import { urlForImage } from '@/lib/sanity'; +import { CommunityT } from 'types'; +import styles from './styles.module.scss'; + +type Props = { + community: CommunityT; +}; + +export default function Community({ community }: Props) { + const { picture, title, description } = community || {}; + const imageUrl = picture?.asset?._ref + ? urlForImage(picture).url() + : 'https://source.unsplash.com/630x441/'; + return ( +
+
+
+
+ community +
+ +
+

{title}

+

+
+
+
+
+ ); +} diff --git a/components/Community/index.ts b/components/Community/index.ts new file mode 100644 index 0000000..e16d7f7 --- /dev/null +++ b/components/Community/index.ts @@ -0,0 +1,3 @@ +import Community from './community'; + +export default Community; diff --git a/components/Community/styles.module.scss b/components/Community/styles.module.scss new file mode 100644 index 0000000..589f738 --- /dev/null +++ b/components/Community/styles.module.scss @@ -0,0 +1,35 @@ +.block { + @apply container px-20 py-20 mx-auto; +} + +.content { + @apply lg:-mx-6 lg:flex; +} + +.right { + @apply lg:w-1/2; +} + +.title { + @apply text-3xl font-bold; + color: #1a1a1a; +} + +.description { + @apply mt-3 text-sm md:text-sm; + color: #1a1a1a; +} + +.link { + @apply inline-flex justify-center text-sm font-semibold py-2.5 px-4 text-white mt-6; + background-color: #191b1d; +} + +.image { + @apply w-full h-72 lg:h-80 lg:mr-32 lg:w-1/2; + position: relative; + + & > span > img { + @apply object-cover; + } +} diff --git a/components/DonationV1/donation-v1.tsx b/components/DonationV1/donation-v1.tsx new file mode 100644 index 0000000..0d741ce --- /dev/null +++ b/components/DonationV1/donation-v1.tsx @@ -0,0 +1,22 @@ +import Link from 'next/link'; +import { DonationV1T } from 'types'; +import styles from './styles.module.scss'; + +type Props = { + donation: DonationV1T; +}; + +export default function DonationV1({ donation }: Props) { + const { title, description, link, titleLink } = donation || {}; + return ( +
+
+

{title}

+ {description} + + {titleLink} + +
+
+ ); +} diff --git a/components/DonationV1/donationV1.tsx b/components/DonationV1/donationV1.tsx deleted file mode 100644 index 57c83ef..0000000 --- a/components/DonationV1/donationV1.tsx +++ /dev/null @@ -1,23 +0,0 @@ -export default function DonationV1() { - return ( -
-
-

- Donation for RS School -

- - Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut - labore et dolore magna aliquat enim eiusmod tempor ad minim - - - Make a donation - -
-
- ); -} diff --git a/components/DonationV1/index.ts b/components/DonationV1/index.ts new file mode 100644 index 0000000..00f85db --- /dev/null +++ b/components/DonationV1/index.ts @@ -0,0 +1,3 @@ +import DonationV1 from './donation-v1'; + +export default DonationV1; diff --git a/components/DonationV1/styles.module.scss b/components/DonationV1/styles.module.scss new file mode 100644 index 0000000..8f92e40 --- /dev/null +++ b/components/DonationV1/styles.module.scss @@ -0,0 +1,21 @@ +.block { + @apply flex flex-col justify-center h-80 text-center px-8 dark:text-white; + background-color: #191b1d; +} + +.container { + @apply flex flex-col justify-center items-center mx-auto md:max-w-[50%]; +} + +.title { + @apply text-slate-900 text-4xl tracking-tight font-extrabold sm:text-5xl dark:text-white; +} + +.description { + @apply mt-6 text-base; +} + +.link { + @apply inline-flex justify-center text-sm font-semibold py-2.5 px-4 bg-white mt-6 ml-8; + color: #191b1d; +} diff --git a/components/DonationV2/donation-v2.tsx b/components/DonationV2/donation-v2.tsx new file mode 100644 index 0000000..f3f3f91 --- /dev/null +++ b/components/DonationV2/donation-v2.tsx @@ -0,0 +1,37 @@ +import Link from 'next/link'; +import Image from 'next/image'; +import { urlForImage } from '@/lib/sanity'; +import { DonationV2T } from 'types'; +import styles from './styles.module.scss'; + +type Props = { + donation: DonationV2T; +}; + +export default function DonationV2({ donation }: Props) { + const { picture, title, description, link, titleLink } = donation || {}; + const imageUrl = picture?.asset?._ref + ? urlForImage(picture).url() + : 'https://source.unsplash.com/630x441/'; + return ( +
+
+

{title}

+ +
+
+ donation +
+ +
+

{description}

+ + + {titleLink} + +
+
+
+
+ ); +} diff --git a/components/DonationV2/index.ts b/components/DonationV2/index.ts new file mode 100644 index 0000000..e90c3e8 --- /dev/null +++ b/components/DonationV2/index.ts @@ -0,0 +1,3 @@ +import DonationV2 from './donation-v2'; + +export default DonationV2; diff --git a/components/DonationV2/styles.module.scss b/components/DonationV2/styles.module.scss new file mode 100644 index 0000000..e3a3208 --- /dev/null +++ b/components/DonationV2/styles.module.scss @@ -0,0 +1,35 @@ +.block { + @apply container px-6 py-10 mx-auto; +} + +.content { + @apply mt-8 lg:-mx-6 lg:flex lg:items-center; +} + +.right { + @apply mt-6 lg:w-1/2 lg:mt-auto; +} + +.title { + @apply text-3xl font-bold; + color: #1a1a1a; +} + +.description { + @apply mt-3 text-sm md:text-sm; + color: #1a1a1a; +} + +.link { + @apply inline-flex justify-center text-sm font-semibold py-2.5 px-4 text-white mt-6; + background-color: #191b1d; +} + +.image { + @apply w-full h-72 lg:h-96 lg:mx-6 lg:w-1/2; + position: relative; + + & > span > img { + @apply object-cover; + } +} diff --git a/components/Footer/footer.tsx b/components/Footer/footer.tsx index a6937d6..6dbb228 100644 --- a/components/Footer/footer.tsx +++ b/components/Footer/footer.tsx @@ -1,6 +1,3 @@ export default function Footer() { - return ( - - ); + return ; } diff --git a/components/Speakers/index.ts b/components/Speakers/index.ts new file mode 100644 index 0000000..aef43d7 --- /dev/null +++ b/components/Speakers/index.ts @@ -0,0 +1,3 @@ +import Speakers from './speakers'; + +export default Speakers; diff --git a/components/Speakers/speakers.tsx b/components/Speakers/speakers.tsx new file mode 100644 index 0000000..b51b639 --- /dev/null +++ b/components/Speakers/speakers.tsx @@ -0,0 +1,22 @@ +import Link from 'next/link'; +import { SpeakersT } from 'types'; +import styles from './styles.module.scss'; + +type Props = { + speaker: SpeakersT; +}; + +export default function Speakers({ speaker }: Props) { + const { title, description, link, titleLink } = speaker || {}; + return ( +
+
+

{title}

+ {description} + + {titleLink} + +
+
+ ); +} diff --git a/components/Speakers/styles.module.scss b/components/Speakers/styles.module.scss new file mode 100644 index 0000000..8f92e40 --- /dev/null +++ b/components/Speakers/styles.module.scss @@ -0,0 +1,21 @@ +.block { + @apply flex flex-col justify-center h-80 text-center px-8 dark:text-white; + background-color: #191b1d; +} + +.container { + @apply flex flex-col justify-center items-center mx-auto md:max-w-[50%]; +} + +.title { + @apply text-slate-900 text-4xl tracking-tight font-extrabold sm:text-5xl dark:text-white; +} + +.description { + @apply mt-6 text-base; +} + +.link { + @apply inline-flex justify-center text-sm font-semibold py-2.5 px-4 bg-white mt-6 ml-8; + color: #191b1d; +} diff --git a/lib/queries/community.js b/lib/queries/community.js new file mode 100644 index 0000000..d4f86db --- /dev/null +++ b/lib/queries/community.js @@ -0,0 +1,12 @@ +import { groq } from 'next-sanity'; + +const communityItem = ` +_id, +title, +description, +picture +`; + +export const communityQuery = groq`*[_type == "community"][]{${communityItem}}`; + +export default communityQuery; diff --git a/lib/queries/donation-v1.js b/lib/queries/donation-v1.js new file mode 100644 index 0000000..b4212ac --- /dev/null +++ b/lib/queries/donation-v1.js @@ -0,0 +1,13 @@ +import { groq } from 'next-sanity'; + +const donationItem = ` +_id, +title, +description, +titleLink, +link +`; + +export const donationV1Query = groq`*[_type == "donation-v1"][]{${donationItem}}`; + +export default donationV1Query; diff --git a/lib/queries/donation-v2.js b/lib/queries/donation-v2.js new file mode 100644 index 0000000..3a4d9c0 --- /dev/null +++ b/lib/queries/donation-v2.js @@ -0,0 +1,14 @@ +import { groq } from 'next-sanity'; + +const donationItem = ` +_id, +title, +description, +titleLink, +link, +picture +`; + +export const donationV2Query = groq`*[_type == "donation-v2"][]{${donationItem}}`; + +export default donationV2Query; diff --git a/lib/queries.js b/lib/queries/examples.js similarity index 100% rename from lib/queries.js rename to lib/queries/examples.js diff --git a/lib/queries/index.js b/lib/queries/index.js new file mode 100644 index 0000000..9a96a00 --- /dev/null +++ b/lib/queries/index.js @@ -0,0 +1,15 @@ +import community from './community'; +import donationV1 from './donation-v1'; +import donationV2 from './donation-v2'; +import speakers from './speakers'; +import socialNetworksList from './social-network'; + +const queries = { + community, + donationV1, + donationV2, + socialNetworksList, + speakers +}; + +export default queries; diff --git a/lib/queries/social-network.js b/lib/queries/social-network.js index 461df3a..2ba530f 100644 --- a/lib/queries/social-network.js +++ b/lib/queries/social-network.js @@ -8,4 +8,4 @@ social_item_link export const socialNetworksListQuery = groq`*[_type == "social_link"][]{${socialItem}}`; -export const test = 'test'; +export default socialNetworksListQuery; diff --git a/lib/queries/speakers.js b/lib/queries/speakers.js new file mode 100644 index 0000000..3b5aa02 --- /dev/null +++ b/lib/queries/speakers.js @@ -0,0 +1,13 @@ +import { groq } from 'next-sanity'; + +const speakersItem = ` +_id, +title, +description, +titleLink, +link +`; + +export const speakersQuery = groq`*[_type == "speakers"][]{${speakersItem}}`; + +export default speakersQuery; diff --git a/pages/api/revalidate.ts b/pages/api/revalidate.ts index 06edc04..ddd293f 100644 --- a/pages/api/revalidate.ts +++ b/pages/api/revalidate.ts @@ -26,7 +26,7 @@ const getQueryForType = type => { }; const log = (msg: string, error?: boolean) => - console[error ? 'error' : 'log'](`[revalidate] ${msg}`); + console[error ? 'error' : 'log'](`[revalidate] ${msg}`); async function readBody(readable) { const chunks = []; @@ -41,11 +41,11 @@ export default async function revalidate(req, res) { const signature = req.headers[SIGNATURE_HEADER_NAME]; const body = await readBody(req); // Read the body into a string if ( - !isValidSignature( - body, - signature, - process.env.SANITY_REVALIDATE_SECRET?.trim() - ) + !isValidSignature( + body, + signature, + process.env.SANITY_REVALIDATE_SECRET?.trim() + ) ) { const invalidSignature = 'Invalid signature'; log(invalidSignature, true); @@ -63,7 +63,7 @@ export default async function revalidate(req, res) { log(`Querying post slug for _id '${id}', type '${_type}' ..`); const slug = await sanityClient.fetch(getQueryForType(_type), { id }); const slugs = (Array.isArray(slug) ? slug : [slug]).map( - _slug => `/posts/${_slug}` + _slug => `/posts/${_slug}` ); const staleRoutes = ['/', ...slugs]; diff --git a/pages/index.tsx b/pages/index.tsx index 0bbf32d..882b2bb 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,35 +1,100 @@ -import { usePreviewSubscription } from '../lib/sanity'; -import { getClient, overlayDrafts } from '../lib/sanity.server'; -import { socialNetworksListQuery } from '../lib/queries/social-network'; -import SocialNetworking from '../components/SocialNetworking'; -import { SocialNetworkingListT } from '../types'; +import { usePreviewSubscription } from '@/lib/sanity'; +import { getClient, overlayDrafts } from '@/lib/sanity.server'; +import queries from '@/lib/queries'; +import SocialNetworking from '@/components/SocialNetworking'; +import DonationV2 from '@/components/DonationV2'; +import DonationV1 from '@/components/DonationV1'; +import Speakers from '@/components/Speakers'; +import Community from '@/components/Community'; +import { + CommunityT, + DonationV1T, + DonationV2T, + SocialNetworkingListT, + SpeakersT +} from '../types'; export default function Index({ socialNetworksList: initialSocialNetworksList, + donationV1: initialDonationV1, + donationV2: initialDonationV2, + speakers: initialSpeakers, + community: initialCommunity, preview }) { + const { data: allDonationV1 } = usePreviewSubscription( + queries.donationV1, + { + initialData: initialDonationV1, + enabled: preview + } + ); + const { data: allDonationV2 } = usePreviewSubscription( + queries.donationV1, + { + initialData: initialDonationV2, + enabled: preview + } + ); + const { data: allCommunity } = usePreviewSubscription( + queries.donationV1, + { + initialData: initialCommunity, + enabled: preview + } + ); const { data: allSocialList } = usePreviewSubscription( - socialNetworksListQuery, + queries.socialNetworksList, { initialData: initialSocialNetworksList, enabled: preview } ); + const { data: allSpeakers } = usePreviewSubscription( + queries.speakers, + { + initialData: initialSpeakers, + enabled: preview + } + ); return ( <> + + + + ); } export async function getStaticProps({ preview = false }) { const socialNetworksList = overlayDrafts( - await getClient(preview).fetch(socialNetworksListQuery) + await getClient(preview).fetch(queries.socialNetworksList) + ); + const donationV1 = overlayDrafts( + await getClient(preview).fetch(queries.donationV1) + ); + const donationV2 = overlayDrafts( + await getClient(preview).fetch(queries.donationV2) + ); + const speakers = overlayDrafts( + await getClient(preview).fetch(queries.speakers) + ); + const community = overlayDrafts( + await getClient(preview).fetch(queries.community) ); return { - props: { socialNetworksList, preview }, + props: { + socialNetworksList, + donationV1, + donationV2, + speakers, + community, + preview + }, // If webhooks isn't setup then attempt to re-generate in 1 minute intervals revalidate: process.env.SANITY_REVALIDATE_SECRET ? undefined : 60 }; diff --git a/studio/schemas/community.js b/studio/schemas/community.js new file mode 100644 index 0000000..0c9900e --- /dev/null +++ b/studio/schemas/community.js @@ -0,0 +1,26 @@ +export default { + name: 'community', + title: 'Community', + type: 'document', + fields: [ + { + name: 'title', + title: 'Title', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'description', + title: 'Description', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'picture', + title: 'Picture', + type: 'image', + options: { hotspot: true }, + validation: Rule => Rule.required() + } + ] +}; diff --git a/studio/schemas/donation-v1.js b/studio/schemas/donation-v1.js new file mode 100644 index 0000000..f6930fe --- /dev/null +++ b/studio/schemas/donation-v1.js @@ -0,0 +1,31 @@ +export default { + name: 'donation-v1', + title: 'Donation-v1', + type: 'document', + fields: [ + { + name: 'title', + title: 'Title', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'description', + title: 'Description', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'titleLink', + title: 'Title Link', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'link', + title: 'Url', + type: 'url', + validation: Rule => Rule.required() + } + ] +}; diff --git a/studio/schemas/donation-v2.js b/studio/schemas/donation-v2.js new file mode 100644 index 0000000..a40eb6e --- /dev/null +++ b/studio/schemas/donation-v2.js @@ -0,0 +1,38 @@ +export default { + name: 'donation-v2', + title: 'Donation-v2', + type: 'document', + fields: [ + { + name: 'title', + title: 'Title', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'description', + title: 'Description', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'titleLink', + title: 'Title Link', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'link', + title: 'Url', + type: 'url', + validation: Rule => Rule.required() + }, + { + name: 'picture', + title: 'Picture', + type: 'image', + options: { hotspot: true }, + validation: Rule => Rule.required() + } + ] +}; diff --git a/studio/schemas/schema.js b/studio/schemas/schema.js index 1687400..48180e4 100644 --- a/studio/schemas/schema.js +++ b/studio/schemas/schema.js @@ -11,6 +11,10 @@ import schemaTypes from 'all:part:@sanity/base/schema-type'; import post from './post'; import author from './author'; import socialLink from './social-link'; +import donationV1 from './donation-v1'; +import donationV2 from './donation-v2'; +import speakers from './speakers'; +import community from './community'; // Then we give our schema to the builder and provide the result to Sanity export default createSchema({ @@ -22,6 +26,10 @@ export default createSchema({ /* Your types here! */ post, author, - socialLink + socialLink, + donationV1, + donationV2, + speakers, + community ]) }); diff --git a/studio/schemas/speakers.js b/studio/schemas/speakers.js new file mode 100644 index 0000000..f1791e7 --- /dev/null +++ b/studio/schemas/speakers.js @@ -0,0 +1,31 @@ +export default { + name: 'speakers', + title: 'Speakers', + type: 'document', + fields: [ + { + name: 'title', + title: 'Title', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'description', + title: 'Description', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'titleLink', + title: 'Title Link', + type: 'string', + validation: Rule => Rule.required() + }, + { + name: 'link', + title: 'Url', + type: 'url', + validation: Rule => Rule.required() + } + ] +}; diff --git a/types/index.ts b/types/index.ts index 92999ee..0f98091 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,3 +1,5 @@ +import { SanityImageObject } from '@sanity/image-url/lib/types/types'; + export type SocialNetworkingItemT = { _id: string; social_item_link: Array<{ @@ -9,4 +11,26 @@ export type SocialNetworkingItemT = { social_name: string; }; +type Link = { + titleLink: string; + link: string; +}; + +type Base = { + title: string; + description: string; +}; + +export type SpeakersT = Base & Link; + +export type DonationV1T = Base & Link; + +export interface DonationV2T extends Base, Link { + picture: SanityImageObject; +} + +export interface CommunityT extends Base { + picture: SanityImageObject; +} + export type SocialNetworkingListT = Array;