diff --git a/src/app/component/Pill.tsx b/src/app/component/Pill.tsx new file mode 100644 index 0000000..a244543 --- /dev/null +++ b/src/app/component/Pill.tsx @@ -0,0 +1,58 @@ +function stringToHexColorAndFont(str: string): { + backgroundColor: string; + color: string; + borderColor: string; +} { + // Hash the input string to get a number + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + + // Convert the hash to a more visually appealing dark hex color + let color = "#"; + for (let i = 0; i < 3; i++) { + // Generate a dark but vivid color by limiting the RGB value to a middle range and adding a base value + const value = (((hash >> (i * 8)) & 0xff) % 128) + 64; // Limit to [64, 191] range for richer colors + color += ("00" + value.toString(16)).slice(-2); + } + + // Convert the hex color to RGB for manipulation + const r = parseInt(color.slice(1, 3), 16); + const g = parseInt(color.slice(3, 5), 16); + const b = parseInt(color.slice(5, 7), 16); + + // Calculate a lighter version of the background color for the font + const lighten = (value: number, amount: number) => + Math.min(255, value + amount); + const fontColor = `#${lighten(r, 200).toString(16).padStart(2, "0")}${lighten(g, 200).toString(16).padStart(2, "0")}${lighten(b, 200).toString(16).padStart(2, "0")}`; + + // Calculate a border color that is between the background and font color + const borderColor = `#${lighten(r, 40).toString(16).padStart(2, "0")}${lighten(g, 40).toString(16).padStart(2, "0")}${lighten(b, 40).toString(16).padStart(2, "0")}`; + + return { + backgroundColor: color, + color: fontColor, + borderColor: borderColor, + }; +} + +type Props = { + name: string; +}; + +export const Pill = ({ name }: Props) => { + const { backgroundColor, borderColor, color } = stringToHexColorAndFont(name); + return ( + + {name} + + ); +}; diff --git a/src/app/globals.css b/src/app/globals.css index 105880a..34c47ab 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,44 +3,31 @@ @tailwind utilities; :root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; } @media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - } + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } } body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient(to bottom, - transparent, - rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb)); + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + transparent, + rgb(var(--background-end-rgb)) + ) + rgb(var(--background-start-rgb)); } @layer utilities { - .text-balance { - text-wrap: balance; - } + .text-balance { + text-wrap: balance; + } } - -.word-pill { - display: inline-block; - background-color: #ff9800; - /* Background color for the pills */ - color: #ffffff; - /* Text color for the pills */ - padding: 5px 10px; - /* Padding inside the pills */ - margin: 5px 5px 5px 0; - /* Space between pills */ - border-radius: 20px; - /* Rounded corners for the pill effect */ - transition: background-color 0.3s ease; - text-decoration: none; -} \ No newline at end of file diff --git a/src/app/lib/data.ts b/src/app/lib/data.ts index 6e56e4c..eff8f0c 100644 --- a/src/app/lib/data.ts +++ b/src/app/lib/data.ts @@ -1,4 +1,4 @@ -// NOTE: use the graph explorer to build new queries +// NOTE: use the graph explorer to build new queries const GET_ALL_POSTS = ` query GetAllPosts($first: Int, $last: Int, $before: String, $after: String, $postedAfter: DateTime, $postedBefore: DateTime) { posts(first: $first, last: $last, before: $before, after: $after, postedAfter: $postedAfter, postedBefore: $postedBefore) { @@ -17,6 +17,7 @@ query GetAllPosts($first: Int, $last: Int, $before: String, $after: String, $pos votesCount topics { nodes { + id description name } @@ -51,6 +52,7 @@ export interface Topic { } export interface Node { + id: string; description: string; name: string; } @@ -105,12 +107,12 @@ function getStartAndEndOfDayInUTC() { export async function getAllPost(): Promise { // Get the current UTC date and time based on PST day const [postedAfter, postedBefore] = Object.values(getStartAndEndOfDayInUTC()); - let hasNextPage = true; + let hasNextPage = true; let after = null; const allPosts: Post[] = []; while (hasNextPage) { - const response = await fetch("https://api.producthunt.com/v2/api/graphql", { + const response = await fetch("https://api.producthunt.com/v2/api/graphql", { headers: { Accept: "application/json", "Content-Type": "application/json", @@ -126,7 +128,7 @@ export async function getAllPost(): Promise { postedBefore: postedBefore, }, }), - }) + }); const result: PostResponse = await response.json(); const data = result.data?.posts; @@ -146,10 +148,10 @@ export const filterPosts = (posts: Post[], showAi = false): Post[] => { "machine learning", ]; - const containsExcludedTerm = (text: string): boolean => - excludedTerms.some(term => text.toLowerCase().includes(term)); + const containsExcludedTerm = (text: string): boolean => + excludedTerms.some((term) => text.toLowerCase().includes(term)); - return posts.filter(post => { + return posts.filter((post) => { if ( containsExcludedTerm(post.name) || containsExcludedTerm(post.tagline) || @@ -160,9 +162,9 @@ export const filterPosts = (posts: Post[], showAi = false): Post[] => { if ( post.topics.nodes.some( - node => + (node) => containsExcludedTerm(node.name) || - containsExcludedTerm(node.description) + containsExcludedTerm(node.description), ) ) { return showAi; diff --git a/src/app/page.tsx b/src/app/page.tsx index 9358c21..25e9c47 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,7 @@ import { Metadata } from "next"; import { Analytics } from "@vercel/analytics/react"; import { filterPosts, Post } from "./lib/data"; +import { Pill } from "./component/Pill"; const META_INFO = { title: "OGHUNT - ZERO AI Slop™", @@ -29,11 +30,11 @@ export const metadata: Metadata = { export default async function Page() { const results: Post[] = await fetch( - "https://pub-3db3ed9313c4427fadfa81f0323b18f8.r2.dev/latest.json", + "https://bigd.oghunt.com/latest.json" ).then((res) => res.json()); const posts = filterPosts(results).sort( - (a, b) => b.votesCount - a.votesCount, + (a, b) => b.votesCount - a.votesCount ); const aiPosts = filterPosts(results, true); @@ -63,14 +64,12 @@ export default async function Page() {

{post.tagline}

-

+

{post.topics && - post.topics.nodes.map(({ name }) => ( - - {name} - + post.topics.nodes.map(({ id, name }) => ( + ))} -

+

{post.description}