mirror of
https://github.com/AnimeThemes/animethemes-web.git
synced 2026-07-11 01:24:31 +02:00
clean: Removed anything billing related (#193)
This commit is contained in:
@@ -71,15 +71,6 @@ export type Audio = {
|
||||
videos: Array<Video>;
|
||||
};
|
||||
|
||||
export type Balance = {
|
||||
date: Scalars['String'];
|
||||
frequency: Scalars['String'];
|
||||
id: Scalars['Int'];
|
||||
month_to_date_balance: Scalars['Float'];
|
||||
service: Scalars['String'];
|
||||
usage: Scalars['Float'];
|
||||
};
|
||||
|
||||
export type Bracket = {
|
||||
currentGroup: Maybe<Scalars['Int']>;
|
||||
currentRound: Maybe<BracketRound>;
|
||||
@@ -207,8 +198,6 @@ export type Query = {
|
||||
announcementAll: Array<Announcement>;
|
||||
artist: Maybe<Artist>;
|
||||
artistAll: Array<Artist>;
|
||||
balanceAll: Array<Balance>;
|
||||
billingMonthAll: Array<Scalars['String']>;
|
||||
bracket: Maybe<Bracket>;
|
||||
bracketAll: Array<Bracket>;
|
||||
dumpAll: Array<Dump>;
|
||||
@@ -233,7 +222,6 @@ export type Query = {
|
||||
studioAll: Array<Studio>;
|
||||
theme: Maybe<Theme>;
|
||||
themeAll: Array<Theme>;
|
||||
transactionAll: Array<Transaction>;
|
||||
videoAll: Array<Video>;
|
||||
year: Maybe<Year>;
|
||||
yearAll: Array<Year>;
|
||||
@@ -264,11 +252,6 @@ export type QueryArtistAllArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryBalanceAllArgs = {
|
||||
month: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
export type QueryBracketArgs = {
|
||||
slug: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
@@ -371,11 +354,6 @@ export type QueryThemeAllArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryTransactionAllArgs = {
|
||||
month: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
export type QueryVideoAllArgs = {
|
||||
limit: InputMaybe<Scalars['Int']>;
|
||||
orderBy: InputMaybe<Scalars['String']>;
|
||||
@@ -467,14 +445,6 @@ export type ThemeSearchResult = EntitySearchResult & {
|
||||
nextPage: Maybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
export type Transaction = {
|
||||
amount: Scalars['Float'];
|
||||
date: Scalars['String'];
|
||||
description: Scalars['String'];
|
||||
id: Scalars['Int'];
|
||||
service: Scalars['String'];
|
||||
};
|
||||
|
||||
export type User = {
|
||||
id: Scalars['Int'];
|
||||
name: Scalars['String'];
|
||||
@@ -740,27 +710,6 @@ export type DumpIndexPageQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
export type DumpIndexPageQuery = { dumpAll: Array<{ path: string, link: string, created_at: string }> };
|
||||
|
||||
export type TransparencyPageBalanceAllFragment = { id: number, date: string, service: string, frequency: string, usage: number, month_to_date_balance: number };
|
||||
|
||||
export type TransparencyPageTransactionAllFragment = { id: number, date: string, service: string, description: string, amount: number };
|
||||
|
||||
export type TransparencyPageMonthsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type TransparencyPageMonthsQuery = { billingMonthAll: Array<string> };
|
||||
|
||||
export type TransparencyPageQueryVariables = Exact<{
|
||||
month: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type TransparencyPageQuery = { balanceAll: Array<{ id: number, date: string, service: string, frequency: string, usage: number, month_to_date_balance: number }>, transactionAll: Array<{ id: number, date: string, service: string, description: string, amount: number }> };
|
||||
|
||||
export type TransparencyPageAllQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type TransparencyPageAllQuery = { balanceAll: Array<{ id: number, date: string, service: string, frequency: string, usage: number, month_to_date_balance: number }>, transactionAll: Array<{ id: number, date: string, service: string, description: string, amount: number }> };
|
||||
|
||||
export type VideoPageAnimeFragment = { name: string, slug: string, year: number | null, season: string | null, media_format: string | null, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string, images: Array<{ link: string, facet: string | null }> } }> } | null, entries: Array<{ episodes: string | null, nsfw: boolean, spoiler: boolean, version: number | null, videos: Array<{ id: number, basename: string, filename: string, lyrics: boolean, nc: boolean, overlap: VideoOverlap, resolution: number | null, source: VideoSource | null, subbed: boolean, uncen: boolean, tags: string, entries: Array<{ theme: { slug: string, type: string, sequence: number | null, group: string | null, id: number, anime: { slug: string, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, videos: Array<{ id: number, basename: string, tags: string, audio: { basename: string } }> }> } }>, audio: { basename: string }, script: { link: string } | null }> }>, anime: { slug: string, name: string, images: Array<{ link: string, facet: string | null }> } }>, images: Array<{ facet: string | null, link: string }>, series: Array<{ slug: string, name: string }>, studios: Array<{ slug: string, name: string }> };
|
||||
|
||||
export type VideoPageQueryVariables = Exact<{
|
||||
@@ -801,19 +750,19 @@ export type RevalidateAnimeQueryVariables = Exact<{
|
||||
|
||||
export type RevalidateAnimeQuery = { anime: { year: number | null, season: string | null, series: Array<{ slug: string }>, studios: Array<{ slug: string }>, themes: Array<{ slug: string, song: { performances: Array<{ artist: { slug: string } }> } | null, entries: Array<{ version: number | null, videos: Array<{ tags: string }> }> }> } | null };
|
||||
|
||||
export type ArtistDetailPageArtistFragment = { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }>, members: Array<{ as: string | null, member: { slug: string, name: string } }>, groups: Array<{ as: string | null, group: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number, title: string, performances: Array<{artist: { slug: string, name: string}, as: string}>}}> } }>, resources: Array<{ link: string | null, site: string | null, as: string | null }>, images: Array<{ facet: string | null, link: string }> };
|
||||
export type ArtistDetailPageArtistFragment = { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number | null, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }>, members: Array<{ as: string | null, member: { slug: string, name: string } }>, groups: Array<{ as: string | null, group: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number | null, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }> } }>, resources: Array<{ link: string | null, site: string | null, as: string | null }>, images: Array<{ facet: string | null, link: string }> };
|
||||
|
||||
export type ArtistDetailPageQueryVariables = Exact<{
|
||||
artistSlug: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ArtistDetailPageQuery = { artist: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }>, members: Array<{ as: string | null, member: { slug: string, name: string } }>, groups: Array<{ as: string | null, group: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number, title: string, performances: Array<{artist: { slug: string, name: string}, as: string}>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }>}}> } }>, resources: Array<{ link: string | null, site: string | null, as: string | null }>, images: Array<{ facet: string | null, link: string }> } | null };
|
||||
export type ArtistDetailPageQuery = { artist: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number | null, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }>, members: Array<{ as: string | null, member: { slug: string, name: string } }>, groups: Array<{ as: string | null, group: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number | null, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }> } }>, resources: Array<{ link: string | null, site: string | null, as: string | null }>, images: Array<{ facet: string | null, link: string }> } | null };
|
||||
|
||||
export type ArtistDetailPageAllQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ArtistDetailPageAllQuery = { artistAll: Array<{ slug: string, name: string, performances: Array<{ as: string | null, song: { id: number, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }>, members: Array<{ as: string | null, member: { slug: string, name: string } }>, groups: Array<{ as: string | null, group: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number, title: string, performances: Array<{artist: { slug: string, name: string}, as: string}>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }>}}> } }>, resources: Array<{ link: string | null, site: string | null, as: string | null }>, images: Array<{ facet: string | null, link: string }> }> };
|
||||
export type ArtistDetailPageAllQuery = { artistAll: Array<{ slug: string, name: string, performances: Array<{ as: string | null, song: { id: number | null, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }>, members: Array<{ as: string | null, member: { slug: string, name: string } }>, groups: Array<{ as: string | null, group: { slug: string, name: string, performances: Array<{ as: string | null, song: { id: number | null, title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }>, themes: Array<{ id: number, slug: string, group: string | null, type: string, sequence: number | null, anime: { slug: string, year: number | null, season: string | null, name: string, images: Array<{ link: string, facet: string | null }> }, song: { title: string | null, performances: Array<{ as: string | null, artist: { slug: string, name: string } }> } | null, entries: Array<{ version: number | null, episodes: string | null, spoiler: boolean, nsfw: boolean, videos: Array<{ id: number, basename: string, tags: string, resolution: number | null, nc: boolean, subbed: boolean, lyrics: boolean, uncen: boolean, source: VideoSource | null, overlap: VideoOverlap, audio: { basename: string } }> }> }> } }> } }>, resources: Array<{ link: string | null, site: string | null, as: string | null }>, images: Array<{ facet: string | null, link: string }> }> };
|
||||
|
||||
export type ArtistIndexPageQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ const resolvers: IResolvers = {
|
||||
featuredTheme: apiResolver({
|
||||
endpoint: () => `/config/wiki`,
|
||||
extractor: (result) => result.wiki.featured_theme,
|
||||
transformer: (featuredTheme) => ({
|
||||
transformer: (featuredTheme) => featuredTheme ? ({
|
||||
animetheme: {
|
||||
...featuredTheme.animethemeentry.animetheme,
|
||||
animethemeentries: [
|
||||
@@ -93,32 +93,18 @@ const resolvers: IResolvers = {
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
}) : null
|
||||
}),
|
||||
dumpAll: apiResolver({
|
||||
endpoint: () => `/dump?fields[dump]=id,path,link,created_at`,
|
||||
extractor: (result) => result.dumps,
|
||||
pagination: true
|
||||
}),
|
||||
balanceAll: apiResolver({
|
||||
endpoint: (_, { month }) => `/balance?${month ? `filter[date]=${month}` : ``}`,
|
||||
extractor: (result) => result.balances,
|
||||
pagination: true
|
||||
}),
|
||||
transactionAll: apiResolver({
|
||||
endpoint: (_, { month }) => `/transaction?${month ? `filter[date]=${month}` : ``}`,
|
||||
extractor: (result) => result.transactions,
|
||||
pagination: true
|
||||
}),
|
||||
announcementAll: apiResolver({
|
||||
endpoint: () => `/announcement`,
|
||||
extractor: (result) => result.announcements,
|
||||
pagination: true
|
||||
}),
|
||||
billingMonthAll: apiResolver({
|
||||
endpoint: () => `/transparency`,
|
||||
extractor: (result) => Object.values(result.transparency.filterOptions),
|
||||
}),
|
||||
playlist: apiResolver({
|
||||
endpoint: (_, { id }) => `/playlist/${id}?fields[playlist]=id,name,visibility,tracks_count`,
|
||||
extractor: (result) => result.playlist,
|
||||
|
||||
@@ -22,9 +22,6 @@ const typeDefs = `
|
||||
imageAll(facet: String): [Image!]!
|
||||
featuredTheme: FeaturedTheme
|
||||
dumpAll: [Dump!]!
|
||||
balanceAll(month: String): [Balance!]!
|
||||
transactionAll(month: String): [Transaction!]!
|
||||
billingMonthAll: [String!]!
|
||||
playlist(id: String!): Playlist
|
||||
announcementAll: [Announcement!]!
|
||||
me: UserScopedQuery!
|
||||
@@ -231,23 +228,6 @@ const typeDefs = `
|
||||
link: String!
|
||||
created_at: String!
|
||||
}
|
||||
|
||||
type Balance {
|
||||
id: Int!
|
||||
date: String!
|
||||
service: String!
|
||||
frequency: String!
|
||||
usage: Float!
|
||||
month_to_date_balance: Float!
|
||||
}
|
||||
|
||||
type Transaction {
|
||||
id: Int!
|
||||
date: String!
|
||||
service: String!
|
||||
description: String!
|
||||
amount: Float!
|
||||
}
|
||||
|
||||
type Playlist {
|
||||
id: String!
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
import type { GetStaticPaths, GetStaticProps } from "next";
|
||||
import { fetchData } from "lib/server";
|
||||
import gql from "graphql-tag";
|
||||
import type { SharedPageProps } from "utils/getSharedPageProps";
|
||||
import getSharedPageProps from "utils/getSharedPageProps";
|
||||
import { Text } from "components/text";
|
||||
import { SEO } from "components/seo";
|
||||
import type { TransparencyPageAllQuery, TransparencyPageMonthsQuery, TransparencyPageQuery } from "generated/graphql";
|
||||
import { Table } from "components/table";
|
||||
import { TableBody, TableCell, TableHead, TableHeadCell, TableRow } from "components/table/Table";
|
||||
import { groupBy, uniq } from "lodash-es";
|
||||
import type { Comparator } from "utils/types";
|
||||
import { Row } from "components/box";
|
||||
import { HorizontalScroll } from "components/utils/HorizontalScroll";
|
||||
import fetchStaticPaths from "utils/fetchStaticPaths";
|
||||
import type { ParsedUrlQuery } from "querystring";
|
||||
import { useRouter } from "next/router";
|
||||
import { Listbox, ListboxOption } from "components/listbox/Listbox";
|
||||
|
||||
interface TransparencyPageProps extends SharedPageProps, TransparencyPageQuery {
|
||||
month: string;
|
||||
months: string[];
|
||||
}
|
||||
|
||||
interface TransparencyPageParams extends ParsedUrlQuery {
|
||||
month: string[];
|
||||
}
|
||||
|
||||
interface HasDate {
|
||||
date: string;
|
||||
}
|
||||
|
||||
const sortByDateDesc: Comparator<HasDate> =
|
||||
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime();
|
||||
|
||||
const toFormattedString = (date: Date) => (
|
||||
date.toLocaleDateString("en", {
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})
|
||||
);
|
||||
|
||||
const currencyFormat = new Intl.NumberFormat("en", {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
});
|
||||
|
||||
export default function TransparencyPage({ month, months, balanceAll, transactionAll }: TransparencyPageProps) {
|
||||
const router = useRouter();
|
||||
|
||||
months.sort((a, b) => new Date(b).getTime() - new Date(a).getTime());
|
||||
|
||||
balanceAll.sort(sortByDateDesc);
|
||||
transactionAll.sort(sortByDateDesc);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SEO title="Transparency"/>
|
||||
<Row $wrap style={{ "--gap": "16px", "--justify-content": "space-between", "--align-items": "center" }}>
|
||||
<Text variant="h1">Transparency</Text>
|
||||
<Listbox value={month} onValueChange={(newMonth) => router.push(`/about/transparency/${newMonth}`)}>
|
||||
{months.map((month) => (
|
||||
<ListboxOption key={month} value={month}>{toFormattedString(new Date(month))}</ListboxOption>
|
||||
))}
|
||||
</Listbox>
|
||||
</Row>
|
||||
<Text variant="h2">Balances</Text>
|
||||
{balanceAll.length ? (
|
||||
<BalanceTable balances={balanceAll}/>
|
||||
) : (
|
||||
<Text>No results found.</Text>
|
||||
)}
|
||||
<Text variant="h2">Transactions</Text>
|
||||
{transactionAll.length ? (
|
||||
<TransactionTable transactions={transactionAll}/>
|
||||
) : (
|
||||
<Text>No results found.</Text>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface BalanceTableProps {
|
||||
balances: TransparencyPageProps["balanceAll"];
|
||||
}
|
||||
|
||||
function BalanceTable({ balances }: BalanceTableProps) {
|
||||
return (
|
||||
<HorizontalScroll fixShadows>
|
||||
<Table style={{ "--columns": "1fr 1fr 1fr 1fr" }}>
|
||||
<TableHead>
|
||||
<TableHeadCell>Service</TableHeadCell>
|
||||
<TableHeadCell>Frequency</TableHeadCell>
|
||||
<TableHeadCell>Month to Date Usage</TableHeadCell>
|
||||
<TableHeadCell>Balance</TableHeadCell>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{balances.map((balance) => (
|
||||
<TableRow key={balance.id}>
|
||||
<TableCell>{balance.service}</TableCell>
|
||||
<TableCell>{balance.frequency}</TableCell>
|
||||
<TableCell>
|
||||
<Text color={balance.usage > 0 ? "text-warning" : balance.usage < 0 ? "text-primary" : undefined}>
|
||||
{currencyFormat.format(balance.usage)}
|
||||
</Text>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Text color={balance.month_to_date_balance < 0 ? "text-warning" : balance.month_to_date_balance > 0 ? "text-primary" : undefined}>
|
||||
{currencyFormat.format(balance.month_to_date_balance)}
|
||||
</Text>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</HorizontalScroll>
|
||||
);
|
||||
}
|
||||
|
||||
interface TransactionTableProps {
|
||||
transactions: TransparencyPageProps["transactionAll"];
|
||||
}
|
||||
|
||||
function TransactionTable({ transactions }: TransactionTableProps) {
|
||||
return (
|
||||
<HorizontalScroll fixShadows>
|
||||
<Table style={{ "--columns": "2fr 2fr 1fr 3fr" }}>
|
||||
<TableHead>
|
||||
<TableHeadCell>Date</TableHeadCell>
|
||||
<TableHeadCell>Service</TableHeadCell>
|
||||
<TableHeadCell>Amount</TableHeadCell>
|
||||
<TableHeadCell>Description</TableHeadCell>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{transactions.map((transaction) => (
|
||||
<TableRow key={transaction.id}>
|
||||
<TableCell>{new Date(transaction.date).toLocaleDateString("en", { dateStyle: "long" })}</TableCell>
|
||||
<TableCell>{transaction.service}</TableCell>
|
||||
<TableCell>
|
||||
<Text color={transaction.amount > 0 ? "text-warning" : transaction.amount < 0 ? "text-primary" : undefined}>
|
||||
{currencyFormat.format(transaction.amount)}
|
||||
</Text>
|
||||
</TableCell>
|
||||
<TableCell>{transaction.description}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</HorizontalScroll>
|
||||
);
|
||||
}
|
||||
|
||||
TransparencyPage.fragments = {
|
||||
balanceAll: gql`
|
||||
fragment TransparencyPageBalanceAll on Balance {
|
||||
id
|
||||
date
|
||||
service
|
||||
frequency
|
||||
usage
|
||||
month_to_date_balance
|
||||
}
|
||||
`,
|
||||
transactionAll: gql`
|
||||
fragment TransparencyPageTransactionAll on Transaction {
|
||||
id
|
||||
date
|
||||
service
|
||||
description
|
||||
amount
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
||||
const buildTimeCache = {
|
||||
pageQueries: new Map<string, TransparencyPageQuery>(),
|
||||
months: null as string[] | null,
|
||||
};
|
||||
|
||||
export const getStaticProps: GetStaticProps<TransparencyPageProps, TransparencyPageParams> = async ({ params }) => {
|
||||
let months = buildTimeCache.months;
|
||||
let apiRequestsTotal = 0;
|
||||
|
||||
if (!months) {
|
||||
const { data, apiRequests } = await fetchData<TransparencyPageMonthsQuery>(gql`
|
||||
query TransparencyPageMonths {
|
||||
billingMonthAll
|
||||
}
|
||||
`);
|
||||
|
||||
months = data.billingMonthAll;
|
||||
apiRequestsTotal += apiRequests;
|
||||
}
|
||||
|
||||
months = months.sort().map((month) => month.substring(0, 7));
|
||||
|
||||
const month = params?.month?.[0] ?? months[months.length - 1];
|
||||
|
||||
let data = month && buildTimeCache.pageQueries.get(month);
|
||||
|
||||
if (!data) {
|
||||
const result = await fetchData<TransparencyPageQuery>(gql`
|
||||
${TransparencyPage.fragments.balanceAll}
|
||||
${TransparencyPage.fragments.transactionAll}
|
||||
|
||||
query TransparencyPage($month: String!) {
|
||||
balanceAll(month: $month) {
|
||||
...TransparencyPageBalanceAll
|
||||
}
|
||||
transactionAll(month: $month) {
|
||||
...TransparencyPageTransactionAll
|
||||
}
|
||||
}
|
||||
`, { month });
|
||||
|
||||
data = result.data;
|
||||
apiRequestsTotal += result.apiRequests;
|
||||
}
|
||||
|
||||
if (!data.balanceAll?.length && !data.transactionAll?.length) {
|
||||
return {
|
||||
notFound: true
|
||||
};
|
||||
}
|
||||
|
||||
const props: TransparencyPageProps = {
|
||||
...getSharedPageProps(apiRequestsTotal),
|
||||
month,
|
||||
months,
|
||||
balanceAll: month ? data.balanceAll.filter((balance) => balance.date.startsWith(month)) : [],
|
||||
transactionAll: month ? data.transactionAll.filter((transaction) => transaction.date.startsWith(month)) : [],
|
||||
};
|
||||
|
||||
return {
|
||||
props,
|
||||
// Revalidate after 3 hours (= 10800 seconds).
|
||||
revalidate: 10800
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths: GetStaticPaths<TransparencyPageParams> = () => {
|
||||
return fetchStaticPaths(async () => {
|
||||
const { data } = await fetchData<TransparencyPageAllQuery>(gql`
|
||||
${TransparencyPage.fragments.balanceAll}
|
||||
${TransparencyPage.fragments.transactionAll}
|
||||
|
||||
query TransparencyPageAll {
|
||||
balanceAll {
|
||||
...TransparencyPageBalanceAll
|
||||
}
|
||||
transactionAll {
|
||||
...TransparencyPageTransactionAll
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const items = [...data.balanceAll, ...data.transactionAll];
|
||||
const months = uniq(items.map((entry) => entry.date.substring(0, 7)));
|
||||
|
||||
const balancesByMonth = groupBy(data.balanceAll, (balance) => balance.date.substring(0, 7));
|
||||
const transactionsByMonth = groupBy(data.transactionAll, (transaction) => transaction.date.substring(0, 7));
|
||||
|
||||
months.forEach((month) => buildTimeCache.pageQueries.set(month, {
|
||||
balanceAll: balancesByMonth[month] ?? [],
|
||||
transactionAll: transactionsByMonth[month] ?? [],
|
||||
}));
|
||||
buildTimeCache.months = months;
|
||||
|
||||
return [
|
||||
{
|
||||
params: {
|
||||
month: [],
|
||||
},
|
||||
},
|
||||
...months.map((month) => ({
|
||||
params: {
|
||||
month: [month],
|
||||
},
|
||||
}))
|
||||
];
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user