diff --git a/app/layout.tsx b/app/layout.tsx index 50b6796..b2b4844 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,18 +1,30 @@ import "@/styles/globals.css"; import { Metadata, Viewport } from "next"; -import { siteConfig } from "@/config/site"; -import { fontSans } from "@/config/fonts"; +import { Fira_Code, Inter } from "next/font/google"; import { Providers } from "./providers"; import { Navbar } from "@/components/navbar"; import { Link } from "@nextui-org/link"; +import { SITE_CONFIG } from "@/data/config"; import clsx from "clsx"; +export const fontSans = Inter({ + subsets: ["latin"], + display: "swap", + variable: "--font-sans", +}); + +export const fontMono = Fira_Code({ + subsets: ["latin"], + display: "swap", + variable: "--font-mono", +}); + export const metadata: Metadata = { title: { - default: siteConfig.name, - template: `%s - ${siteConfig.name}`, + default: SITE_CONFIG.name, + template: `%s - ${SITE_CONFIG.name}`, }, - description: siteConfig.description, + description: SITE_CONFIG.description, icons: { icon: "/favicon.ico", shortcut: "/favicon-16x16.png", @@ -33,14 +45,13 @@ export default function RootLayout({ children: React.ReactNode; }) { return ( - + - +
diff --git a/app/page.tsx b/app/page.tsx index bb229e1..6d7ccf1 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,7 +1,7 @@ import Filter from "@/components/filter"; import { title, subtitle } from "@/components/primitives"; import Search from "@/components/search"; -import { search, languages } from "@/data/items"; +import { SEARCH_OPTIONS, LANGUAGES_OPTIONS } from "@/data/filters"; export default function Home() { return ( @@ -12,14 +12,22 @@ export default function Home() {
- +

Banner

- - + + {/*
= ({ + size = 36, + width, + height, + ...props +}) => ( + + + +); + +export const HeartFilledIcon = ({ + size = 24, + width, + height, + ...props +}: IconSvgProps) => ( + +); + +export const SearchIcon = (props: IconSvgProps) => ( + +); + +export const ChevronOpenIcon = (props: IconSvgProps) => ( + + + + + + +); + +export const ChevronDownIcon = (props: IconSvgProps) => ( + + + +); + +export const DiscordIcon: React.FC = ({ + size = 24, + width, + height, + ...props +}) => { + return ( + + + + ); +}; + +export const TwitterIcon: React.FC = ({ + size = 24, + width, + height, + ...props +}) => { + return ( + + + + ); +}; + +export const GithubIcon: React.FC = ({ + size = 24, + width, + height, + ...props +}) => { + return ( + + + + ); +}; diff --git a/components/bounties.tsx b/components/bounties.tsx index a9da217..316bd20 100644 --- a/components/bounties.tsx +++ b/components/bounties.tsx @@ -8,8 +8,8 @@ import { DropdownItem, } from "@nextui-org/dropdown"; import { Slider } from "@nextui-org/slider"; -import { ChevronOpenIcon } from "./utils/icons/chevronOpenIcon"; -import Emoji from "./utils/emoji"; +import { ChevronOpenIcon } from "@/assets/icons"; +import Emoji from "./emoji"; interface BountiesProps { currency: string; diff --git a/components/contributions-table/row.tsx b/components/contributions-table/row.tsx index f7f5036..242fa6f 100644 --- a/components/contributions-table/row.tsx +++ b/components/contributions-table/row.tsx @@ -1,7 +1,7 @@ import { Chip } from "@nextui-org/chip"; import { Link } from "@nextui-org/link"; import MyImage from "@/components/ui/image"; -import { daysSince } from "@/utils/helpers"; +import { daysSince } from "@/utils/date"; import { useState, useRef, useEffect } from "react"; interface IProjectProps { diff --git a/components/utils/emoji.tsx b/components/emoji.tsx similarity index 100% rename from components/utils/emoji.tsx rename to components/emoji.tsx diff --git a/components/filter.tsx b/components/filter.tsx index 61c0e99..2032285 100644 --- a/components/filter.tsx +++ b/components/filter.tsx @@ -1,13 +1,13 @@ "use client"; import React, { FC } from "react"; import { Select, SelectItem } from "@nextui-org/select"; -import { Item } from "@/components/utils/types/item"; -import Emoji from "./utils/emoji"; +import { FilterItem } from "@/types/filters"; +import Emoji from "./emoji"; interface FilterProps { placeholder: string; emoji: string; - items: Item[]; + items: FilterItem[]; } export const Filter: FC = ({ placeholder, items, emoji }) => { return ( diff --git a/components/icons.tsx b/components/icons.tsx deleted file mode 100644 index 7bfe973..0000000 --- a/components/icons.tsx +++ /dev/null @@ -1,214 +0,0 @@ -import * as React from "react"; -import { IconSvgProps } from "../types/index"; - -export const Logo: React.FC = ({ - size = 36, - width, - height, - ...props -}) => ( - - - -); - -export const DiscordIcon: React.FC = ({ - size = 24, - width, - height, - ...props -}) => { - return ( - - - - ); -}; - -export const TwitterIcon: React.FC = ({ - size = 24, - width, - height, - ...props -}) => { - return ( - - - - ); -}; - -export const GithubIcon: React.FC = ({ - size = 24, - width, - height, - ...props -}) => { - return ( - - - - ); -}; - -export const MoonFilledIcon = ({ - size = 24, - width, - height, - ...props -}: IconSvgProps) => ( - -); - -export const SunFilledIcon = ({ - size = 24, - width, - height, - ...props -}: IconSvgProps) => ( - -); - -export const HeartFilledIcon = ({ - size = 24, - width, - height, - ...props -}: IconSvgProps) => ( - -); - -export const SearchIcon = (props: IconSvgProps) => ( - -); - -export const NextUILogo: React.FC = (props) => { - const { width, height = 40 } = props; - - return ( - - - - - - ); -}; diff --git a/components/loadMore.tsx b/components/loadMore.tsx index cf6d928..eae8f91 100644 --- a/components/loadMore.tsx +++ b/components/loadMore.tsx @@ -1,14 +1,16 @@ "use client"; -import { isValidNotionPage, daysSince, getImagePath } from "@/utils/helpers"; import { Spinner } from "@nextui-org/spinner"; import { useEffect, useState } from "react"; import { QueryDatabaseResponse } from "@notionhq/client/build/src/api-endpoints"; import projectLogosJson from "@/public/images/imageMap.json"; import { useInView } from "react-intersection-observer"; import Row from "./row"; -import { getGoodFirstIssues } from "@/actions/notion"; -import { LoadMoreState } from "@/types"; +import { getGoodFirstIssues } from "@/lib/notion"; +import { LoadMoreState } from "@/lib/notion/types"; +import { isValidNotionPage } from "@/lib/notion/utils"; +import { daysSince } from "@/utils/date"; +import { getImagePath } from "@/utils/github"; export function LoadMore({ cursor }: { cursor: string }) { const { ref, inView } = useInView(); diff --git a/components/navbar.tsx b/components/navbar.tsx index 0d2ccbb..e61f053 100644 --- a/components/navbar.tsx +++ b/components/navbar.tsx @@ -1,32 +1,17 @@ import { Navbar as NextUINavbar, NavbarContent, - NavbarMenu, NavbarMenuToggle, NavbarBrand, NavbarItem, - NavbarMenuItem, } from "@nextui-org/navbar"; import { Button } from "@nextui-org/button"; import { Kbd } from "@nextui-org/kbd"; import { Link } from "@nextui-org/link"; import { Input } from "@nextui-org/input"; - -import { link as linkStyles } from "@nextui-org/theme"; - -import { siteConfig } from "@/config/site"; +import { SITE_CONFIG } from "@/data/config"; import NextLink from "next/link"; -import clsx from "clsx"; - -import { - TwitterIcon, - GithubIcon, - DiscordIcon, - HeartFilledIcon, - SearchIcon, -} from "@/components/icons"; - -import { Logo } from "@/components/icons"; +import { GithubIcon, HeartFilledIcon, Logo, SearchIcon } from "@/assets/icons"; export const Navbar = () => { const searchInput = ( @@ -59,22 +44,6 @@ export const Navbar = () => {

ACME

-
    - {siteConfig.navItems.map((item) => ( - - - {item.label} - - - ))} -
{ justify="end" > - - - - - - - + @@ -98,7 +61,6 @@ export const Navbar = () => { isExternal as={Link} className="text-sm font-normal text-default-600 bg-default-100" - href={siteConfig.links.sponsor} startContent={} variant="flat" > @@ -108,34 +70,11 @@ export const Navbar = () => { - + - - - {searchInput} -
- {siteConfig.navMenuItems.map((item, index) => ( - - - {item.label} - - - ))} -
-
); }; diff --git a/components/search.tsx b/components/search.tsx index ed0eb21..16d0167 100644 --- a/components/search.tsx +++ b/components/search.tsx @@ -1,13 +1,13 @@ "use client"; import React, { FC } from "react"; import { Autocomplete, AutocompleteItem } from "@nextui-org/autocomplete"; -import Emoji from "../components/utils/emoji"; -import { Item } from "../components/utils/types/item"; +import { FilterItem } from "@/types/filters"; +import Emoji from "./emoji"; interface SearchProps { placeholder: string; emoji: string; - items: Item[]; + items: FilterItem[]; } const Search: FC = ({ @@ -26,7 +26,7 @@ const Search: FC = ({ size="lg" allowsCustomValue={true} > - {(item: Item) => ( + {(item: FilterItem) => (   diff --git a/components/utils/icons/chevronDownIcon.tsx b/components/utils/icons/chevronDownIcon.tsx deleted file mode 100644 index 46551b5..0000000 --- a/components/utils/icons/chevronDownIcon.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; - -export const ChevronDownIcon = () => ( - - - -); diff --git a/components/utils/icons/chevronOpenIcon.tsx b/components/utils/icons/chevronOpenIcon.tsx deleted file mode 100644 index 3387548..0000000 --- a/components/utils/icons/chevronOpenIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; - -export const ChevronOpenIcon = () => ( - - - - - - -); diff --git a/config/fonts.ts b/config/fonts.ts deleted file mode 100644 index 0e7d9c9..0000000 --- a/config/fonts.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Fira_Code as FontMono, Inter as FontSans } from "next/font/google"; - -export const fontSans = FontSans({ - subsets: ["latin"], - variable: "--font-sans", -}); - -export const fontMono = FontMono({ - subsets: ["latin"], - variable: "--font-mono", -}); diff --git a/config/site.ts b/config/site.ts deleted file mode 100644 index 5390e9a..0000000 --- a/config/site.ts +++ /dev/null @@ -1,25 +0,0 @@ -export type SiteConfig = typeof siteConfig; - -export const siteConfig = { - name: "Next.js + NextUI", - description: "Make beautiful websites regardless of your design experience.", - navItems: [ - { - label: "Home", - href: "/", - }, - ], - navMenuItems: [ - { - label: "Help & Feedback", - href: "/help-feedback", - }, - ], - links: { - github: "https://github.com/nextui-org/nextui", - twitter: "https://twitter.com/getnextui", - docs: "https://nextui.org", - discord: "https://discord.gg/9b6yyZKmH4", - sponsor: "https://patreon.com/jrgarciadev", - }, -}; diff --git a/data/config.ts b/data/config.ts new file mode 100644 index 0000000..fad8ee3 --- /dev/null +++ b/data/config.ts @@ -0,0 +1,8 @@ +export const SITE_CONFIG = { + name: "Kudos Portal", + description: + "A portal for the Substrate, Polkadot and Kusama ecosystem contributors. Find collaborations, collect kudos.", + links: { + github: "https://github.com/kudos-ink", + }, +}; diff --git a/data/items.tsx b/data/filters.tsx similarity index 98% rename from data/items.tsx rename to data/filters.tsx index ce05b1b..12d4cdf 100644 --- a/data/items.tsx +++ b/data/filters.tsx @@ -1,4 +1,4 @@ -export const search = [ +export const SEARCH_OPTIONS = [ { value: "senior", emoji: "👵", label: "Senior" }, { value: "engineer", emoji: "🤓", label: "Engineer" }, { value: "dev", emoji: "🤓", label: "Developer" }, @@ -51,7 +51,7 @@ export const search = [ { value: "php", emoji: "🐘", label: "PHP" }, ]; -export const languages = [ +export const LANGUAGES_OPTIONS = [ { value: "Assembly", label: "Assembly", emoji: "🔧" }, // Assembly // { value: "Astro", label: "Astro", emoji: "" }, // { value: "Batchfile", label: "Batchfile", emoji: "" }, diff --git a/types.ts b/lib/notion/constants.ts similarity index 61% rename from types.ts rename to lib/notion/constants.ts index 76052ff..7f2e05d 100644 --- a/types.ts +++ b/lib/notion/constants.ts @@ -1,11 +1,8 @@ -import { - QueryDatabaseResponse, - QueryDatabaseParameters, -} from "@notionhq/client/build/src/api-endpoints"; +import { ValidSort } from "./types"; -export const databaseId = "bc9fe682dbe04550b121303a2befad8a"; +export const DATABASE_ID = "bc9fe682dbe04550b121303a2befad8a"; -export const repoLinkToPageIdMap = { +export const REPO_LINK_TO_PAGE_ID_MAP = { "https://github.com/automata-network/automata": "094fe93b-27b7-4547-b604-98a700c905e5", "https://github.com/subspace/subspace": @@ -126,7 +123,7 @@ export const repoLinkToPageIdMap = { "fc87cecc-505c-40cb-bf10-9235830b4a33", } as const; -const fieldnameToPropertyIdMap = { +export const FIELDNAME_TO_PROPERTY_ID_MAP = { "Project Name": "yag%5C", "Issue Title": "title", "Issue Link": "CpBm", @@ -143,192 +140,21 @@ const fieldnameToPropertyIdMap = { // "Issue State": "zPlX", } as const; -export const defaultFilterProperties = [ - fieldnameToPropertyIdMap["Issue Link"], - fieldnameToPropertyIdMap["Issue Title"], - fieldnameToPropertyIdMap["Opened By"], - fieldnameToPropertyIdMap["Project Name"], - fieldnameToPropertyIdMap["Repo Language"], - fieldnameToPropertyIdMap["Assignee"], - fieldnameToPropertyIdMap["Opened Date"], - fieldnameToPropertyIdMap["Issue Labels"], - fieldnameToPropertyIdMap["Github Repo"], +export const DEFAULT_FILTER_PROPERTIES = [ + FIELDNAME_TO_PROPERTY_ID_MAP["Issue Link"], + FIELDNAME_TO_PROPERTY_ID_MAP["Issue Title"], + FIELDNAME_TO_PROPERTY_ID_MAP["Opened By"], + FIELDNAME_TO_PROPERTY_ID_MAP["Project Name"], + FIELDNAME_TO_PROPERTY_ID_MAP["Repo Language"], + FIELDNAME_TO_PROPERTY_ID_MAP["Assignee"], + FIELDNAME_TO_PROPERTY_ID_MAP["Opened Date"], + FIELDNAME_TO_PROPERTY_ID_MAP["Issue Labels"], + FIELDNAME_TO_PROPERTY_ID_MAP["Github Repo"], ]; -export const defaultSort = [ +export const DEFAULT_SORT = [ { property: "Opened Date", direction: "descending", }, ] as ValidSort; - -export type ValueOf = T[keyof T]; -export type ValidRepositoryLink = keyof typeof repoLinkToPageIdMap; -export type ValidFilterProperty = ValueOf; -export type ValidSortProperty = keyof typeof fieldnameToPropertyIdMap; -export type ValidSort = Array< - | { - property: ValidSortProperty; - direction: "ascending" | "descending"; - } - | { - timestamp: "created_time" | "last_edited_time"; - direction: "ascending" | "descending"; - } ->; - -export type KudosQueryParameters = Omit< - QueryDatabaseParameters, - "database_id" | "filter_properties" | "sorts" -> & { - database_id?: string; - filter_properties?: Array; - sorts?: ValidSort; -}; -export type ValidNotionResponse = { - object: string; - id: string; - created_time: Date; - last_edited_time: Date; - created_by: User; - last_edited_by: User; - cover: null; - icon: null; - parent: Parent; - archived: boolean; - properties: Properties; - url: string; - public_url: string; -}; - -export type User = { - object: string; - id: string; -}; - -export type Parent = { - type: string; - database_id: string; -}; - -export type Properties = { - "Issue Link": Assignee; - "Issue Title": IssueTitle; - "Opened By": Assignee; - "Project Name": ProjectName; - "Repo Language": RepoLanguage; - Assignee: Assignee; - "Opened Date": OpenedDate; - "Issue Labels": IssueLabels; - "Github Repo": GithubRepo; -}; - -export type Assignee = { - id: string; - type: string; - url: string; -}; - -export type GithubRepo = { - id: string; - type: string; - relation: Relation[]; - has_more: boolean; -}; - -export type Relation = { - id: string; -}; - -export type IssueLabels = { - id: string; - type: string; - multi_select: MultiSelect[]; -}; - -export type MultiSelect = { - id: string; - name: string; - color: string; -}; - -export type IssueTitle = { - id: string; - type: string; - title: RichText[]; -}; - -export type RichText = { - type: string; - text: Text; - annotations: Annotations; - plain_text: string; - href: null; -}; - -export type Annotations = { - bold: boolean; - italic: boolean; - strikethrough: boolean; - underline: boolean; - code: boolean; - color: string; -}; - -export type Text = { - content: string; - link: null; -}; - -export type OpenedDate = { - id: string; - type: string; - date: DateClass; -}; - -export type DateClass = { - start: Date; - end: null; - time_zone: null; -}; - -export type ProjectName = { - id: string; - type: string; - rollup: ProjectNameRollup; -}; - -export type ProjectNameRollup = { - type: string; - array: ProjectNameArray[]; - function: string; -}; - -export type ProjectNameArray = { - type: string; - rich_text: RichText[]; -}; - -export type RepoLanguage = { - id: string; - type: string; - rollup: RepoLanguageRollup; -}; - -export type RepoLanguageRollup = { - type: string; - array: RepoLanguageSelectArray[]; - function: string; -}; - -export type RepoLanguageSelectArray = { - type: string; - multi_select: MultiSelect[]; -}; - -export type ProjectLogoImages = Record; - -export type LoadMoreState = { - data: QueryDatabaseResponse[]; - nextCursor: string | undefined; -}; diff --git a/actions/notion.ts b/lib/notion/index.ts similarity index 84% rename from actions/notion.ts rename to lib/notion/index.ts index 405e607..8c05d43 100644 --- a/actions/notion.ts +++ b/lib/notion/index.ts @@ -5,15 +5,14 @@ import { QueryDatabaseParameters, } from "@notionhq/client/build/src/api-endpoints"; import "dotenv/config"; -import { subtractMonths } from "../utils/helpers"; +import { subtractMonths } from "../../utils/date"; import { - KudosQueryParameters, - databaseId, - defaultFilterProperties, - defaultSort, - ValidRepositoryLink, - repoLinkToPageIdMap, -} from "@/types"; + DATABASE_ID, + DEFAULT_FILTER_PROPERTIES, + DEFAULT_SORT, + REPO_LINK_TO_PAGE_ID_MAP, +} from "./constants"; +import { KudosQueryParameters, ValidRepositoryLink } from "./types"; const notion = new Client({ auth: process.env.NOTION_API_KEY, @@ -36,9 +35,9 @@ export async function queryDatabase( queryOverrides: Partial = {}, ): Promise { const defaultQuery: KudosQueryParameters = { - database_id: databaseId, - filter_properties: defaultFilterProperties, - sorts: defaultSort, + database_id: DATABASE_ID, + filter_properties: DEFAULT_FILTER_PROPERTIES, + sorts: DEFAULT_SORT, page_size: 100, start_cursor: undefined, filter: undefined, @@ -51,10 +50,10 @@ export async function queryDatabase( } export async function getGoodFirstIssues({ - database_id = databaseId, + database_id = DATABASE_ID, page_size = 100, - filter_properties = defaultFilterProperties, - sorts = defaultSort, + filter_properties = DEFAULT_FILTER_PROPERTIES, + sorts = DEFAULT_SORT, start_cursor, }: KudosQueryParameters = {}): Promise { return await queryDatabase({ @@ -89,10 +88,10 @@ export async function getGoodFirstIssues({ } export async function getBugIssues({ - database_id = databaseId, + database_id = DATABASE_ID, page_size = 100, - filter_properties = defaultFilterProperties, - sorts = defaultSort, + filter_properties = DEFAULT_FILTER_PROPERTIES, + sorts = DEFAULT_SORT, start_cursor, }: KudosQueryParameters = {}): Promise { return await queryDatabase({ @@ -110,10 +109,10 @@ export async function getBugIssues({ }); } export async function getUnassignedIssues({ - database_id = databaseId, + database_id = DATABASE_ID, page_size = 100, - filter_properties = defaultFilterProperties, - sorts = defaultSort, + filter_properties = DEFAULT_FILTER_PROPERTIES, + sorts = DEFAULT_SORT, start_cursor, }: KudosQueryParameters = {}): Promise { return await queryDatabase({ @@ -132,10 +131,10 @@ export async function getUnassignedIssues({ } export async function getIssuesOpenedWithin3Months({ - database_id = databaseId, + database_id = DATABASE_ID, page_size = 100, - filter_properties = defaultFilterProperties, - sorts = defaultSort, + filter_properties = DEFAULT_FILTER_PROPERTIES, + sorts = DEFAULT_SORT, start_cursor, }: KudosQueryParameters = {}): Promise { return await queryDatabase({ @@ -154,10 +153,10 @@ export async function getIssuesOpenedWithin3Months({ } export async function getIssuesOpenedWithin1Month({ - database_id = databaseId, + database_id = DATABASE_ID, page_size = 100, - filter_properties = defaultFilterProperties, - sorts = defaultSort, + filter_properties = DEFAULT_FILTER_PROPERTIES, + sorts = DEFAULT_SORT, start_cursor, }: KudosQueryParameters = {}): Promise { return await queryDatabase({ @@ -180,10 +179,10 @@ export async function getIssuesOpenedWithin1Month({ export async function getIssuesByProject( projectName: string, { - database_id = databaseId, + database_id = DATABASE_ID, page_size = 100, - filter_properties = defaultFilterProperties, - sorts = defaultSort, + filter_properties = DEFAULT_FILTER_PROPERTIES, + sorts = DEFAULT_SORT, start_cursor, }: KudosQueryParameters = {}, ): Promise { @@ -209,10 +208,10 @@ export async function getIssuesByProject( export async function getIssuesByRepo( repoLink: ValidRepositoryLink, { - database_id = databaseId, + database_id = DATABASE_ID, page_size = 100, - filter_properties = defaultFilterProperties, - sorts = defaultSort, + filter_properties = DEFAULT_FILTER_PROPERTIES, + sorts = DEFAULT_SORT, start_cursor, }: KudosQueryParameters = {}, ): Promise { @@ -220,7 +219,7 @@ export async function getIssuesByRepo( filter: { property: "Github Repo", relation: { - contains: repoLinkToPageIdMap[repoLink], + contains: REPO_LINK_TO_PAGE_ID_MAP[repoLink], }, }, page_size, diff --git a/lib/notion/types.ts b/lib/notion/types.ts new file mode 100644 index 0000000..8122b27 --- /dev/null +++ b/lib/notion/types.ts @@ -0,0 +1,179 @@ +import { + QueryDatabaseResponse, + QueryDatabaseParameters, +} from "@notionhq/client/build/src/api-endpoints"; +import { + FIELDNAME_TO_PROPERTY_ID_MAP, + REPO_LINK_TO_PAGE_ID_MAP, +} from "./constants"; + +export type ValueOf = T[keyof T]; +export type ValidRepositoryLink = keyof typeof REPO_LINK_TO_PAGE_ID_MAP; +export type ValidFilterProperty = ValueOf; +export type ValidSortProperty = keyof typeof FIELDNAME_TO_PROPERTY_ID_MAP; +export type ValidSort = Array< + | { + property: ValidSortProperty; + direction: "ascending" | "descending"; + } + | { + timestamp: "created_time" | "last_edited_time"; + direction: "ascending" | "descending"; + } +>; + +export type KudosQueryParameters = Omit< + QueryDatabaseParameters, + "database_id" | "filter_properties" | "sorts" +> & { + database_id?: string; + filter_properties?: Array; + sorts?: ValidSort; +}; +export type ValidNotionResponse = { + object: string; + id: string; + created_time: Date; + last_edited_time: Date; + created_by: User; + last_edited_by: User; + cover: null; + icon: null; + parent: Parent; + archived: boolean; + properties: Properties; + url: string; + public_url: string; +}; + +export type User = { + object: string; + id: string; +}; + +export type Parent = { + type: string; + database_id: string; +}; + +export type Properties = { + "Issue Link": Assignee; + "Issue Title": IssueTitle; + "Opened By": Assignee; + "Project Name": ProjectName; + "Repo Language": RepoLanguage; + Assignee: Assignee; + "Opened Date": OpenedDate; + "Issue Labels": IssueLabels; + "Github Repo": GithubRepo; +}; + +export type Assignee = { + id: string; + type: string; + url: string; +}; + +export type GithubRepo = { + id: string; + type: string; + relation: Relation[]; + has_more: boolean; +}; + +export type Relation = { + id: string; +}; + +export type IssueLabels = { + id: string; + type: string; + multi_select: MultiSelect[]; +}; + +export type MultiSelect = { + id: string; + name: string; + color: string; +}; + +export type IssueTitle = { + id: string; + type: string; + title: RichText[]; +}; + +export type RichText = { + type: string; + text: Text; + annotations: Annotations; + plain_text: string; + href: null; +}; + +export type Annotations = { + bold: boolean; + italic: boolean; + strikethrough: boolean; + underline: boolean; + code: boolean; + color: string; +}; + +export type Text = { + content: string; + link: null; +}; + +export type OpenedDate = { + id: string; + type: string; + date: DateClass; +}; + +export type DateClass = { + start: Date; + end: null; + time_zone: null; +}; + +export type ProjectName = { + id: string; + type: string; + rollup: ProjectNameRollup; +}; + +export type ProjectNameRollup = { + type: string; + array: ProjectNameArray[]; + function: string; +}; + +export type ProjectNameArray = { + type: string; + rich_text: RichText[]; +}; + +export type RepoLanguage = { + id: string; + type: string; + rollup: RepoLanguageRollup; +}; + +export type RepoLanguageRollup = { + type: string; + array: RepoLanguageSelectArray[]; + function: string; +}; + +export type RepoLanguageSelectArray = { + type: string; + multi_select: MultiSelect[]; +}; + +export type ProjectLogoImages = Record; + +export type LoadMoreState = { + data: QueryDatabaseResponse[]; + nextCursor: string | undefined; +}; diff --git a/lib/notion/utils.ts b/lib/notion/utils.ts new file mode 100644 index 0000000..7843bec --- /dev/null +++ b/lib/notion/utils.ts @@ -0,0 +1,5 @@ +import { ValidNotionResponse } from "./types"; + +export function isValidNotionPage(object: any): object is ValidNotionResponse { + return object && object.object === "page" && "properties" in object; +} diff --git a/styles/globals.css b/styles/globals.css index 808dfdf..b5c61c9 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -1,6 +1,3 @@ -@import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap"); @tailwind base; @tailwind components; @tailwind utilities; diff --git a/tailwind.config.js b/tailwind.config.js index 628feda..4320c90 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -11,8 +11,8 @@ module.exports = { theme: { extend: { fontFamily: { - "open-sans": ["Open Sans"], - "fira-code": ["Fira Code"], + sans: ["var(--font-sans)"], + mono: ["var(--font-mono)"], emoji: ["Noto Color Emoji"], }, }, diff --git a/components/utils/types/item.tsx b/types/filters.ts similarity index 54% rename from components/utils/types/item.tsx rename to types/filters.ts index 5c7e20a..0116f7d 100644 --- a/components/utils/types/item.tsx +++ b/types/filters.ts @@ -1,7 +1,5 @@ -interface Item { +export type FilterItem = { label: string; emoji: string; value: string; -} - -export type { Item }; +}; diff --git a/utils/contribution.ts b/utils/contribution.ts index 54d1af4..313fa5e 100644 --- a/utils/contribution.ts +++ b/utils/contribution.ts @@ -1,6 +1,6 @@ import projectLogosJson from "@/public/images/imageMap.json"; import { Contribution } from "@/types/contribution"; -import { getImagePath } from "./helpers"; +import { getImagePath } from "./github"; export function transformNotionDataToContributions( notionData: any, diff --git a/utils/helpers.ts b/utils/date.ts similarity index 51% rename from utils/helpers.ts rename to utils/date.ts index 81831ce..fade251 100644 --- a/utils/helpers.ts +++ b/utils/date.ts @@ -1,5 +1,3 @@ -import { ValidNotionResponse, ProjectLogoImages } from "@/types"; - export function subtractMonths(date: Date, numberOfMonths: number): Date { const result = new Date(date.getTime()); result.setMonth(result.getMonth() - numberOfMonths); @@ -15,17 +13,3 @@ export function daysSince(date: Date) { return differenceInDays; } - -export function isValidNotionPage(object: any): object is ValidNotionResponse { - return object && object.object === "page" && "properties" in object; -} - -export function getImagePath( - githubUrl: string, - projectLogos: ProjectLogoImages, -): string { - return ( - "/images/" + projectLogos[githubUrl] || - "https://avatars.githubusercontent.com/u/86160567?s=200&v=4" - ); -} diff --git a/utils/github.ts b/utils/github.ts new file mode 100644 index 0000000..bbcc71a --- /dev/null +++ b/utils/github.ts @@ -0,0 +1,11 @@ +import { ProjectLogoImages } from "@/lib/notion/types"; + +export function getImagePath( + githubUrl: string, + projectLogos: ProjectLogoImages, +): string { + return ( + "/images/" + projectLogos[githubUrl] || + "https://avatars.githubusercontent.com/u/86160567?s=200&v=4" + ); +}