diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 6d35067..4e3d8cf 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -50,7 +50,8 @@ "firefoxAddons": "Firefox Add-ons", "youtube": "YouTube", "hexpm": "Hex", - "fly": "Fly.io" + "fly": "Fly.io", + "productHunt": "Product Hunt" }, "showMore": "show more", "try": "How about this?", diff --git a/src/components/cards/index.tsx b/src/components/cards/index.tsx index 722cc19..f4030a2 100644 --- a/src/components/cards/index.tsx +++ b/src/components/cards/index.tsx @@ -33,6 +33,7 @@ import TwitterCard from './providers/Twitter'; import VercelCard from './providers/Vercel'; import YouTubeCard from './providers/YouTube'; import FlyIoCard from './providers/FlyIo'; +import ProductHuntCard from './providers/ProductHunt'; const Index: React.FC<{ query: string }> = ({ query }) => { const { @@ -69,6 +70,7 @@ const Index: React.FC<{ query: string }> = ({ query }) => { + diff --git a/src/components/cards/providers/ProductHunt.tsx b/src/components/cards/providers/ProductHunt.tsx new file mode 100644 index 0000000..bd34f6d --- /dev/null +++ b/src/components/cards/providers/ProductHunt.tsx @@ -0,0 +1,192 @@ +import useFetch from 'fetch-suspense'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { FaProductHunt } from 'react-icons/fa'; +import { Card, Result } from '../core'; + +const Search: React.FC<{ query: string }> = ({ query }) => { + const { t } = useTranslation(); + const response = useFetch( + `https://0h4smabbsg-dsn.algolia.net/1/indexes/Post_production?query=${encodeURIComponent( + query + )}`, + { + headers: { + 'X-Algolia-API-Key': '9670d2d619b9d07859448d7628eea5f3', + 'X-Algolia-Application-Id': '0H4SMABBSG', + }, + } + ) as Response; + + const hits = response.hits; + + return ( + <> + {hits.length > 0 ? ( + hits + .slice(0, 10) + .map((hit) => ( + } + key={hit.id} + /> + )) + ) : ( + } + /> + )} + + ); +}; + +const ProductHuntCard: React.FC<{ query: string }> = ({ query }) => { + const { t } = useTranslation(); + + return ( + + + + ); +}; + +export default ProductHuntCard; + +interface Response { + hits: Hit[]; + nbHits: number; + page: number; + nbPages: number; + hitsPerPage: number; + exhaustiveNbHits: boolean; + exhaustiveTypo: boolean; + query: Query; + params: string; + processingTimeMS: number; +} + +interface Hit { + comments_count: number; + name: string; + slug: string; + tagline: string; + topics: Topic[]; + id: number; + user_id: number; + thumbnail_image_uuid?: string; + created_at: string; + featured_at: null | string; + exclusive: null; + is_featured: boolean; + media: Media[]; + posted_date: number; + product_links: ProductLink[]; + product_state: ProductState; + shortened_url: string; + text_content: any[]; + url: string; + user: User; + vote_count: number; + objectID: string; + _highlightResult: HighlightResult; + thumbnail?: Thumbnail; +} + +interface HighlightResult { + name: Name; + tagline: Name; +} + +interface Name { + value: string; + matchLevel: MatchLevel; + fullyHighlighted?: boolean; + matchedWords: Query[]; +} + +export enum MatchLevel { + Full = 'full', + None = 'none', +} + +export enum Query { + Namae = 'namae', +} + +interface Media { + id: number; + metadata: MediaMetadata; + original_height: number; + original_width: number; + image_url: string; + image_uuid: string; + media_type: MediaType; +} + +export enum MediaType { + Image = 'image', + Video = 'video', +} + +interface MediaMetadata { + video_id?: null | string; + url?: null | string; + kindle_asin?: null; + platform?: null; +} + +interface ProductLink { + store_name: StoreName; + id: number; + url: string; +} + +export enum StoreName { + AppStore = 'App Store', + Chrome = 'Chrome', + PlayStore = 'Play Store', + Website = 'Website', +} + +export enum ProductState { + Default = 'default', + NoLongerOnline = 'no_longer_online', +} + +interface Thumbnail { + image_uuid: string; + media_type: MediaType; + metadata: ThumbnailMetadata; + original_height: number; + id: number; + original_width: number; + image_url: string; +} + +interface ThumbnailMetadata {} + +interface Topic { + id: number; + name: string; + description: string; + slug: string; + followers_count: number; + image_uuid: string; +} + +interface User { + username: string; + id: number; + twitter_username: null | string; + name: string; + headline: null | string; + image_urls: { [key: string]: string }; + link: string; + avatar_url: string; + is_maker: boolean; +} diff --git a/src/util/i18n.ts b/src/util/i18n.ts index fcc5111..97aa63c 100644 --- a/src/util/i18n.ts +++ b/src/util/i18n.ts @@ -5,7 +5,7 @@ import XHR from 'i18next-xhr-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; -const TRANSLATION_VERSION = '17'; +const TRANSLATION_VERSION = '18'; i18n .use(Backend)