diff --git a/app/components/Album/ErrorBoundary.tsx b/app/components/Album/ErrorBoundary.tsx index 86bc9c2..d77f4b8 100644 --- a/app/components/Album/ErrorBoundary.tsx +++ b/app/components/Album/ErrorBoundary.tsx @@ -6,7 +6,6 @@ import { Container, EmojiText, Heading, - Layout, Typography, } from '~/components/Base' import Document from '~/components/Base/Document' @@ -37,30 +36,28 @@ const AlbumErrorBoundary: React.FC = () => { return ( - - -
- ⛔️ Whoops! - - We seemed to have run into an error. We are working on fixing it - now. You should refresh the page to fix this issue. - -
- Detailed error message -
{body}
-
- - - Retry - - -
-
-
+ +
+ ⛔️ Whoops! + + We seemed to have run into an error. We are working on fixing it + now. You should refresh the page to fix this issue. + +
+ Detailed error message +
{body}
+
+ + + Retry + + +
+
) } diff --git a/app/components/Album/ReviewLink.tsx b/app/components/Album/ReviewLink.tsx new file mode 100644 index 0000000..b8a03ec --- /dev/null +++ b/app/components/Album/ReviewLink.tsx @@ -0,0 +1,111 @@ +import { A, Heading } from '~/components/Base' +import useUTM from '~/hooks/useUTM' + +interface Props { + publicationSlug: string + publicationName: string + reviewURL: string | null + className?: string +} + +const ReviewLink: React.FC = ({ + publicationSlug, + publicationName, + reviewURL, + className, +}) => { + const { createExternalURL } = useUTM() + + if (!reviewURL?.startsWith('http')) { + return null + } + + const url = createExternalURL(reviewURL, { + utm_campaign: 'publication', + utm_term: publicationSlug, + }) + + if (publicationSlug === 'pitchfork') { + return ( + + Read the{' '} + + Pitchfork Review + + + ) + } else if (publicationSlug === 'needle-drop') { + return ( + + Watch the{' '} + + Needle Drop review on YouTube + + + ) + } else if (publicationSlug === '33-13-sound') { + return ( + + Buy the{' '} + + {publicationName} book + {' '} + about this album + + ) + } else if (publicationSlug === 'robert-christgau') { + return ( + + {url.pathname.includes('get_album.php') ? ( + <> + Read{' '} + + {publicationName}'s Consumer Guide™️{' '} + {' '} + for this album + + ) : ( + <> + Read{' '} + + {publicationName}'s musings + {' '} + about this artist + + )} + + ) + } else if (publicationSlug === 'resident-advisor') { + return ( + + Read the{' '} + + Resident Advisor Review + + + ) + } else if ( + publicationSlug === 'bandcamp-daily' && + reviewURL.startsWith('https://') + ) { + return ( + + Read the{' '} + + Bandcamp Daily review + + + ) + } else { + return ( + + Read the{' '} + + {publicationName} review + + + ) + } +} + +export default ReviewLink diff --git a/app/components/Base/HomeSection.tsx b/app/components/Base/HomeSection.tsx index 89384c9..d90be71 100644 --- a/app/components/Base/HomeSection.tsx +++ b/app/components/Base/HomeSection.tsx @@ -1,4 +1,4 @@ -import clsx from 'clsx' +import { cn } from '~/lib/util' import { Heading, Typography } from '~/components/Base' @@ -15,12 +15,12 @@ const HomeSection: React.FC> = ({ className, }) => { return ( -
- +
+ {title} {typeof subtitle === 'string' ? ( - + {subtitle} ) : ( diff --git a/app/components/Base/Layout.tsx b/app/components/Base/Layout.tsx deleted file mode 100644 index c3afbed..0000000 --- a/app/components/Base/Layout.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import clsx from 'clsx' -import React from 'react' -import { ClientOnly } from 'remix-utils/client-only' - -import AutoAlert from '~/components/AutoAlert' -import { DesktopLoader, MobileLoader } from '~/components/Loading' -import SearchBreadcrumbs, { - SearchBreadcrumbsProps, -} from '~/components/SearchBreadcrumbs' -import useLoading from '~/hooks/useLoading' -import { useIsMobile } from '~/hooks/useMediaQuery' - -import { A, ButtonLink, Container, EmojiText, Link } from './index' - -interface LayoutProps { - className?: string - headerBreadcrumbs?: SearchBreadcrumbsProps['crumbs'] - hideFooter?: boolean -} - -const Layout: React.FC> = ({ - children, - className, - headerBreadcrumbs, - hideFooter = false, -}) => { - const { loading } = useLoading() - const isMobile = useIsMobile() - - return ( - <> -
- - -

- - - Album Mode.party{' '} - - -

- {headerBreadcrumbs && ( - .breadcrumbs]:md:py-0', - )} - crumbs={headerBreadcrumbs} - /> - )} -
- - - Library - - -
-
-
-
- {children} -
- {!hideFooter && ( - - - - )} - - {() => isMobile && } - - ) -} - -export default Layout diff --git a/app/components/Base/index.tsx b/app/components/Base/index.tsx index 08a0b7c..614c727 100644 --- a/app/components/Base/index.tsx +++ b/app/components/Base/index.tsx @@ -5,7 +5,6 @@ import React from 'react' import { cn } from '~/lib/util' -export { default as Layout } from './Layout' export { default as EmojiText } from './EmojiText' const headingVariants = cva('', { diff --git a/app/components/ErrorBoundary.tsx b/app/components/ErrorBoundary.tsx index 0106c28..86f636e 100644 --- a/app/components/ErrorBoundary.tsx +++ b/app/components/ErrorBoundary.tsx @@ -6,7 +6,6 @@ import { Container, EmojiText, Heading, - Layout, Typography, } from '~/components/Base' import Document from '~/components/Base/Document' @@ -33,26 +32,23 @@ export const PageErrorBoundary: React.FC = () => { return ( - - -
- ⛔️ Whoops! - - We seem to have run into an error. We are working on fixing it - now. - -
- Detailed error message -
{body}
-
- - - Head Home - - -
-
-
+ +
+ ⛔️ Whoops! + + We seem to have run into an error. We are working on fixing it now. + +
+ Detailed error message +
{body}
+
+ + + Head Home + + +
+
) } diff --git a/app/components/Forms/FunSelect.tsx b/app/components/Forms/FunSelect.tsx index 619b448..b7a14e6 100644 --- a/app/components/Forms/FunSelect.tsx +++ b/app/components/Forms/FunSelect.tsx @@ -9,20 +9,24 @@ import { useCallback, useState } from 'react' import { cn } from '~/lib/util' -export interface Option { +export type Option< + T extends Record = Record, +> = T & { label?: string labelElement?: React.ReactNode value: string } -interface FunSelectProps { +interface FunSelectProps< + T extends Record = Record, +> { name: string label?: string - value?: Option + value?: Option className?: string placeholder?: string - loadOptions: (query?: string) => Promise - onChange: (value?: Option) => void + loadOptions: (query?: string) => Promise[]> + onChange: (value?: Option) => void } const FunSelect: React.FC = ({ @@ -34,6 +38,7 @@ const FunSelect: React.FC = ({ loadOptions, onChange, }) => { + const [input, setInput] = useState('') const [options, setOptions] = useState([]) const [selectedOption, setSelectedOption] = useState