-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
36 changed files
with
1,621 additions
and
37 deletions.
There are no files selected for viewing
54 changes: 54 additions & 0 deletions
54
apps/web/src/app/(cms)/faq/(root)/components/get-in-touch.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { ChatBubbleOvalLeftIcon, TicketIcon } from '@heroicons/react/24/solid' | ||
import { Button } from '@sushiswap/ui' | ||
import React, { FC } from 'react' | ||
|
||
interface Block { | ||
title: string | ||
button: { text: string; link: string } | ||
icon: FC<React.ComponentProps<'svg'>> | ||
} | ||
|
||
function Block({ title, button, icon: Icon }: Block) { | ||
return ( | ||
<div className="px-7 py-5 flex flex-row justify-between w-full space-x-4 bg-white dark:bg-opacity-5 bg-opacity-[0.12] rounded-xl border border-black border-opacity-30 dark:border-opacity-10 dark:border-white"> | ||
<div className="flex-col flex space-y-5"> | ||
<div>{title}</div> | ||
<a target="_blank" rel="noreferrer" href={button.link}> | ||
<Button size="xs" className="py-2 px-3"> | ||
{button.text} | ||
</Button> | ||
</a> | ||
</div> | ||
<div className="relative w-[55px] aspect-1"> | ||
<div className="absolute opacity-20 rounded-full bg-blue-500 w-[55px] aspect-1 bottom-0 right-0" /> | ||
<div className="absolute opacity-20 rounded-full bg-[#F338C3] w-[52px] aspect-1 bottom-0 right-0" /> | ||
<div className="absolute w-[55px] aspect-1 bottom-0 right-0 flex justify-center items-center pl-px text-white"> | ||
<Icon width={26} height={26} className="w-[26px] h-[26px]" /> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export function GetInTouch() { | ||
return ( | ||
<div className="grid md:grid-cols-2 gap-6"> | ||
<Block | ||
title={`Can’t find what you are looking for?`} | ||
button={{ | ||
text: `Chat with us`, | ||
link: 'https://discord.com/channels/748031363935895552/1141943831898636410', | ||
}} | ||
icon={ChatBubbleOvalLeftIcon} | ||
/> | ||
<Block | ||
title={`Looking for more support on a specific issue?`} | ||
button={{ | ||
text: `Raise a ticket`, | ||
link: '', | ||
}} | ||
icon={TicketIcon} | ||
/> | ||
</div> | ||
) | ||
} |
37 changes: 37 additions & 0 deletions
37
apps/web/src/app/(cms)/faq/(root)/components/help-by-categories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { classNames } from '@sushiswap/ui' | ||
import Link from 'next/link' | ||
|
||
import { | ||
type FaqCategories, | ||
getFaqCategories, | ||
} from '@sushiswap/graph-client/strapi' | ||
|
||
function Block({ name, url }: FaqCategories[number]) { | ||
return ( | ||
<Link | ||
href={url} | ||
className={classNames( | ||
'md:text-lg md:py-3 md:px-5 px-4 py-2 rounded-lg text-sm whitespace-nowrap border', | ||
'bg-black bg-opacity-5 border-black border-opacity-30', | ||
'dark:bg-white dark:bg-opacity-5 dark:border-slate-500 dark:border-opacity-20', | ||
)} | ||
> | ||
{name} | ||
</Link> | ||
) | ||
} | ||
|
||
export async function HelpByCategories() { | ||
const categories = await getFaqCategories({ sort: ['id'] }) | ||
|
||
return ( | ||
<div className="md:space-y-12 space-y-8"> | ||
<div className="text-2xl font-medium">Help By Categories</div> | ||
<div className="flex flex-wrap gap-x-3 md:gap-x-6 gap-y-3 md:gap-y-4"> | ||
{categories.map((topic) => ( | ||
<Block key={topic.slug} {...topic} /> | ||
))} | ||
</div> | ||
</div> | ||
) | ||
} |
51 changes: 51 additions & 0 deletions
51
apps/web/src/app/(cms)/faq/(root)/components/help-by-products.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { | ||
type FaqProducts, | ||
getFaqProducts, | ||
} from '@sushiswap/graph-client/strapi' | ||
import { CloudinaryImage, classNames } from '@sushiswap/ui' | ||
import Link from 'next/link' | ||
|
||
function Block({ name, description, url, image }: FaqProducts[number]) { | ||
return ( | ||
<Link | ||
href={url} | ||
className={classNames( | ||
'flex flex-col justify-center md:text-lg md:py-6 px-3 py-4 rounded-lg text-sm border items-center space-y-6', | ||
'bg-black bg-opacity-[0.02] border-black border-opacity-30', | ||
'dark:bg-white dark:bg-opacity-5 dark:border-slate-500 dark:border-opacity-20', | ||
)} | ||
> | ||
{image ? ( | ||
<CloudinaryImage | ||
alt={image.alternativeText} | ||
src={image.provider_metadata.public_id as string} | ||
width={image.width} | ||
height={image.height} | ||
sizes="100vw" | ||
className="h-14 w-min" | ||
/> | ||
) : null} | ||
<div className="space-y-3 flex flex-col justify-center text-center"> | ||
<div className="text-lg font-bold">{name}</div> | ||
<div className="text-sm dark:text-white text-opacity-70"> | ||
{description} | ||
</div> | ||
</div> | ||
</Link> | ||
) | ||
} | ||
|
||
export async function HelpByProducts() { | ||
const products = await getFaqProducts() | ||
|
||
return ( | ||
<div className="md:space-y-12 space-y-8"> | ||
<div className="text-2xl font-medium">Help By Products</div> | ||
<div className="lg:grid-cols-4 xs:grid-cols-2 md:grid-cols-3 grid gap-x-5 md:gap-y-8 gap-y-4"> | ||
{products.map((product, i) => ( | ||
<Block key={i} {...product} /> | ||
))} | ||
</div> | ||
</div> | ||
) | ||
} |
84 changes: 84 additions & 0 deletions
84
apps/web/src/app/(cms)/faq/(root)/components/most-searched-questions.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { ChevronRightIcon } from '@heroicons/react/24/solid' | ||
import { | ||
FaqMostSearched, | ||
getFaqMostSearched, | ||
} from '@sushiswap/graph-client/strapi' | ||
import Link from 'next/link' | ||
|
||
function Question({ question, url }: FaqMostSearched[number]) { | ||
return ( | ||
<div className=""> | ||
<Link | ||
href={url} | ||
className="flex flex-row items-center justify-between space-x-4" | ||
prefetch={true} | ||
> | ||
<div className="dark:hover:text-slate-300 hover:text-neutral-600"> | ||
{question} | ||
</div> | ||
<div> | ||
<ChevronRightIcon width={28} height={28} /> | ||
</div> | ||
</Link> | ||
</div> | ||
) | ||
} | ||
|
||
function MostSearchedQuestionsDesktop({ | ||
questions, | ||
}: { questions: FaqMostSearched }) { | ||
const firstHalf = questions.slice(0, Math.ceil(questions.length / 2)) | ||
const secondHalf = questions.slice(Math.ceil(questions.length / 2)) | ||
|
||
return ( | ||
<div className="grid grid-cols-2 gap-x-16 lg:gap-x-24"> | ||
<div className="divide-y divide-slate-500 divide-opacity-50"> | ||
{firstHalf.map((topic, i) => ( | ||
<div key={i} className="pt-2.5 pb-2.5 first:pt-0 last:pb-0"> | ||
<Question {...topic} /> | ||
</div> | ||
))} | ||
</div> | ||
<div className="divide-y divide-slate-500 divide-opacity-50"> | ||
{secondHalf.map((topic, i) => ( | ||
<div key={i} className="pt-2.5 pb-2.5 first:pt-0 last:pb-0"> | ||
<Question {...topic} /> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
function MostSearchedQuestionsMobile({ | ||
questions, | ||
}: { questions: FaqMostSearched }) { | ||
return ( | ||
<div className="divide-y divide-slate-500 divide-opacity-50 gap-y-4"> | ||
{questions.map((topic, i) => ( | ||
<div key={i} className="first:pt-0 py-3 last:pb-0"> | ||
<Question {...topic} /> | ||
</div> | ||
))} | ||
</div> | ||
) | ||
} | ||
|
||
export async function MostSearchedQuestions() { | ||
const questions = await getFaqMostSearched() | ||
|
||
return ( | ||
<div className="flex flex-col space-y-8 md:space-y-12"> | ||
<div className="text-2xl font-medium">Most Searched Questions</div> | ||
|
||
<div> | ||
<div className="md:block hidden"> | ||
<MostSearchedQuestionsDesktop questions={questions} /> | ||
</div> | ||
<div className="md:hidden block"> | ||
<MostSearchedQuestionsMobile questions={questions} /> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
146 changes: 146 additions & 0 deletions
146
apps/web/src/app/(cms)/faq/(root)/components/search-box.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
'use client' | ||
|
||
import { useDebounce, useOnClickOutside } from '@sushiswap/hooks' | ||
import { LinkInternal, SkeletonText, classNames } from '@sushiswap/ui' | ||
import { useRef, useState } from 'react' | ||
|
||
import { SearchIcon } from '@heroicons/react-v1/outline' | ||
import { XIcon } from '@heroicons/react-v1/solid' | ||
import { getFaqAnswerSearch } from '@sushiswap/graph-client/strapi' | ||
import { useQuery } from '@tanstack/react-query' | ||
|
||
export function SearchBox() { | ||
const ref = useRef<HTMLDivElement>(null) | ||
const [query, setQuery] = useState<string>('') | ||
const debouncedQuery = useDebounce(query, 300) | ||
const [open, setOpen] = useState(false) | ||
|
||
useOnClickOutside(ref, () => { | ||
setOpen(false) | ||
}) | ||
|
||
const { data, isLoading, isError } = useQuery({ | ||
queryKey: ['faq-answers', debouncedQuery], | ||
queryFn: () => getFaqAnswerSearch({ search: debouncedQuery }), | ||
}) | ||
|
||
return ( | ||
<div className="flex flex-col gap-3 relative"> | ||
<div className="z-10 flex w-full gap-4"> | ||
<div | ||
ref={ref} | ||
onFocus={() => setOpen(true)} | ||
className={classNames( | ||
'rounded-xl w-full border', | ||
'border-black border-opacity-30 bg-neutral-100', | ||
'dark:bg-[#1F2535] dark:border-opacity-20 dark:border-slate-500', | ||
)} | ||
> | ||
<div className="flex items-center gap-2 pl-4 pr-3 h-14"> | ||
<div className="flex gap-2 items-center w-full"> | ||
<div className="w-6 h-6"> | ||
<SearchIcon | ||
width={24} | ||
height={24} | ||
className="dark:text-slate-500 text-neutral-950" | ||
/> | ||
</div> | ||
<input | ||
value={query} | ||
onChange={(e) => setQuery(e.target.value)} | ||
placeholder="Search questions, keyword, articles..." | ||
className={classNames( | ||
'w-full dark:placeholder:text-slate-500 placeholder:text-neutral-950', | ||
'p-0 bg-transparent border-none focus:outline-none focus:ring-0 w-full truncate font-medium text-left text-base md:text-sm placeholder:font-normal', | ||
)} | ||
/> | ||
</div> | ||
{query && ( | ||
<XIcon | ||
onClick={() => setQuery('')} | ||
className="w-6 h-6 cursor-pointer dark:text-slate-500 text-neutral-950" | ||
/> | ||
)} | ||
</div> | ||
<div | ||
className={classNames( | ||
open | ||
? 'max-h-[335px] py-2 border-b border-l border-r -ml-px scroll' | ||
: 'max-h-[0px]', | ||
'z-[100] rounded-b-xl flex flex-col gap-2 overflow-hidden transition-all absolute w-full -mt-4 ', | ||
'dark:bg-[#1F2535] dark:border-opacity-20 dark:border-slate-500', | ||
'border-black border-opacity-30 bg-neutral-100', | ||
)} | ||
> | ||
{isError ? ( | ||
<div className="px-4 pt-4 pb-2 gap-2 flex justify-center w-full text-sm"> | ||
An unexpected error has occured. | ||
</div> | ||
) : ( | ||
<> | ||
<p className="text-sm font-semibold mt-4 px-4 text-slate-400"> | ||
Questions | ||
</p> | ||
<RowGroup entries={data?.answers || []} isLoading={isLoading} /> | ||
<p className="text-sm font-semibold mt-4 px-4 text-slate-400"> | ||
Question Groups | ||
</p> | ||
<RowGroup | ||
entries={data?.answerGroups || []} | ||
isLoading={isLoading} | ||
/> | ||
</> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
function RowGroup({ | ||
entries, | ||
isLoading, | ||
}: { | ||
entries: { name: string; slug: string }[] | ||
isLoading: boolean | ||
}) { | ||
if (isLoading) { | ||
return ( | ||
<div className="px-4 py-2 gap-2"> | ||
<SkeletonText /> | ||
<SkeletonText /> | ||
<SkeletonText /> | ||
</div> | ||
) | ||
} | ||
|
||
if (entries.length === 0) { | ||
return ( | ||
<div className="px-4 py-2 gap-2 flex w-full text-sm"> | ||
No results found. | ||
</div> | ||
) | ||
} | ||
|
||
return ( | ||
<> | ||
{entries.map(({ name, slug }) => ( | ||
<Row key={slug} name={name} slug={slug} /> | ||
))} | ||
</> | ||
) | ||
} | ||
|
||
function Row({ name, slug }: { name: string; slug: string }) { | ||
const content = ( | ||
<div | ||
className="flex items-center gap-2 px-4 py-2 cursor-pointer dark:hover:bg-slate-700 hover:bg-neutral-200" | ||
key={slug} | ||
> | ||
<p className="font-medium">{name}</p> | ||
</div> | ||
) | ||
|
||
return <LinkInternal href={`/faq/${slug}`}>{content}</LinkInternal> | ||
} |
Oops, something went wrong.