Skip to content

Commit

Permalink
done category page
Browse files Browse the repository at this point in the history
  • Loading branch information
karambarakat committed Oct 6, 2023
1 parent 5098b0d commit 44d6fa8
Show file tree
Hide file tree
Showing 50 changed files with 1,127 additions and 1,167 deletions.
72 changes: 51 additions & 21 deletions apps/frontend/src/.storybook/storybook-decorator.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
/// <reference path="../../types/SB.d.ts" />
import React from 'react'
import React, { useMemo } from 'react'
import { Suspense } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import MetaContext from '../routes/_MetaContext'
import { BrowserRouter, Router } from 'react-router-dom'
import Loading from '../routes/_Loading'
import ErrorComponent from '../routes/_Error'
import { QueryClientProvider, useQueryClient } from '@tanstack/react-query'
import { queryClient } from '../api/client'
import {
QueryClient,
QueryClientProvider,
useQueryClient,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'

export function ProvidersDeprecated({ Story }: { Story: () => JSX.Element }) {
Expand Down Expand Up @@ -35,28 +38,55 @@ export function ProvidersDeprecated({ Story }: { Story: () => JSX.Element }) {
// import { } from '@storybook/react'
// import {} from 'SB'

export const frontend_decorator: SB.Decorator[] = [
(Story, ctx) => {
return (
<>
<QueryClientProvider client={queryClient}>
{
Story() // prettier 😠
}
<div tabIndex={-1}>
<ReactQueryDevtools initialIsOpen={false} position="bottom-right" />
</div>
</QueryClientProvider>
</>
)
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
suspense: true,
retry: false,
useErrorBoundary: false,
},
},
})

export const frontend_decorator: SB.Decorator[] = [
// (Story, ctx) => {
// if (!ctx.parameters?.query) {
// return Story()
// }

// const client = useQueryClient()

// client.clear()
// ctx.parameters.query.data?.forEach(({ data, key }) => {
// client.setQueryData(key, data)
// })

// return <Story />
// },

(Story, ctx) => {
const CleanUp = useMemo(() => {
return () => {
const client = useQueryClient()

client.clear()
ctx.parameters?.query?.data?.forEach(({ data, key }) => {
client.setQueryData(key, data)
})

return <></>
}
}, [ctx.parameters?.query])

if (ctx.parameters?.query) {
useQueryClient().clear()
return <Story />
return (
<QueryClientProvider client={queryClient}>
{Story()}
<CleanUp />
<ReactQueryDevtools />
</QueryClientProvider>
)
}

return <Story />
return Story() // prettier 😠
},
]
86 changes: 51 additions & 35 deletions apps/frontend/src/api/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as queries from './queries'
import { UserRestResponse, BasicToken, RegisterUserBody } from 'types/backend'
import { GraphqlError, RestError } from 'types/HttpError'
import {
CategoryFragment,
EntryFragment,
Mutation,
MutationCreateOneCategoryArgs,
MutationCreateOneEntryArgs,
Expand All @@ -12,30 +14,35 @@ import {
MutationUpdateOneCategoryArgs,
MutationUpdateOneEntryArgs,
MutationUpdatePasswordArgs,
QueryGetAllEntriesArgs,
User,
UserFragment,
} from 'types/gql/graphql'
import { token } from '../utils/localStorage'

export const user = 'id email displayName avatar providers createdAt updatedAt'
export const category = `id title color createdAt updatedAt createdBy { ${user} }`
export const entry = `id title amount note createdAt updatedAt createdBy { ${user} } category { ${category} }`
import { QueryClient } from '@tanstack/react-query'
import { Category, Entry, User as User_F } from 'types/fragments'

export const create_entry = async (_input: MutationCreateOneEntryArgs) => {
const res = await gql(
`mutation mutate($entry: EntryInput!) {
createOneEntry(entry: $entry) {
${entry}
...Entry
}
}`,
}
${Entry}
`,
{ entry: _input.entry },
)

return (await handler(res)).createOneEntry as Mutation['createOneEntry']
return (await handler(res)).createOneEntry as EntryFragment
}

create_entry.shouldInvalidate = ['find_log'] as const satisfies Readonly<
(keyof typeof queries)[]
>
create_entry.shouldInvalidate = (
c: QueryClient,
p: QueryGetAllEntriesArgs['pagination'],
) => {
c.invalidateQueries(['find_log', p] satisfies queryKeys)
}

export const update_entry = async ({
entry,
Expand All @@ -62,29 +69,35 @@ export const delete_entry = async ({ id }: MutationDeleteOneEntryArgs) => {
return (await handler(res)).deleteOneEntry as Mutation['deleteOneEntry']
}

delete_entry.shouldInvalidate = [
'find_log',
'find_one_log',
] as const satisfies Readonly<(keyof typeof queries)[]>
delete_entry.shouldInvalidate = (
c: QueryClient,
pagination: QueryGetAllEntriesArgs['pagination'],
id: { id: string },
) => {
c.invalidateQueries(['find_log', pagination] satisfies queryKeys)
c.invalidateQueries(['find_one_log', id] satisfies queryKeys)
}

export const create_category = async ({
category,
}: MutationCreateOneCategoryArgs) => {
const res = await gql(
`mutation mutate($category: CategoryInput!) {
createOneCategory(category: $category) {
${category}
...Category
}
}`,
}
${Category}
`,
{ category },
)

return (await handler(res)).createOneCategory as Mutation['createOneCategory']
return (await handler(res)).createOneCategory as CategoryFragment
}

create_category.shouldInvalidate = [
'find_category',
] as const satisfies Readonly<(keyof typeof queries)[]>
create_category.shouldInvalidate = (c: QueryClient) => {
c.invalidateQueries(['find_category'] satisfies queryKeys)
}

export const update_category = async ({
category,
Expand All @@ -100,10 +113,10 @@ export const update_category = async ({
return (await handler(res)).updateOneCategory as Mutation['updateOneCategory']
}

update_category.shouldInvalidate = [
'find_category',
'find_one_category',
] as const satisfies Readonly<(keyof typeof queries)[]>
update_category.shouldInvalidate = (c: QueryClient, id: { id: string }) => {
c.invalidateQueries(['find_category'] satisfies queryKeys)
c.invalidateQueries(['find_one_category', id] satisfies queryKeys)
}

export const delete_category = async ({
id,
Expand All @@ -118,10 +131,10 @@ export const delete_category = async ({
return (await handler(res)).deleteOneCategory as Mutation['deleteOneCategory']
}

delete_category.shouldInvalidate = [
'find_category',
'find_one_category',
] as const satisfies Readonly<(keyof typeof queries)[]>
delete_category.shouldInvalidate = (c: QueryClient, id: { id: string }) => {
c.invalidateQueries(['find_category'] satisfies queryKeys)
c.invalidateQueries(['find_one_category', id] satisfies queryKeys)
}

export const register = async (
{ email, password, ...body }: BasicToken & RegisterUserBody,
Expand Down Expand Up @@ -157,6 +170,7 @@ export const login = async ({ email, password }: BasicToken) => {
}

import { DateTime } from 'luxon'
import { queryKeys } from '.'

// graphql does some transformation that actix-web does not
// this is a hack to unify the two
Expand All @@ -175,13 +189,15 @@ export const update_profile = async ({
const res = await gql(
`mutation mutate($user: UserInput!) {
updateCurrentUser(user: $user) {
${user}
...User
}
}`,
}
${User_F}
`,
{ user },
)

return (await handler(res)).updateCurrentUser as Mutation['updateCurrentUser']
return (await handler(res)).updateCurrentUser as UserFragment
}

export const set_password = async ({
Expand Down Expand Up @@ -217,12 +233,12 @@ export async function handler(res: Response) {
throw new RestError(json.error)
}

if ('data' in json) {
return json.data
if ('errors' in json) {
throw new GraphqlError(json.errors)
}

if ('errors' in json && json.data === null) {
throw new GraphqlError(json.errors)
if ('data' in json) {
return json.data
}

throw new Error('Response is not JSON')
Expand Down
49 changes: 33 additions & 16 deletions apps/frontend/src/api/queries.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,95 @@
import {
CategoryFragment,
EntryFragment,
Query,
QueryGetAllEntriesArgs,
QueryGetOneCategoryArgs,
QueryGetOneEntryArgs,
UserFragment,
} from 'types/gql/graphql'
import { category, entry, gql, handler, user } from './mutations'
import { gql, handler } from './mutations'
import { Category, Entry, User } from 'types/fragments'

export const find_log = async (
pagination: QueryGetAllEntriesArgs['pagination'],
) => {
const res = await gql(
`query query($pagination: PaginationRequest!) {
getAllEntries(pagination: $pagination) {
data { ${entry} }
data { ...Entry }
page
pageSize
total
totalPages
}
}`,
}
${Entry}
`,
{ pagination },
)

return (await handler(res)).getAllEntries as Query['getAllEntries']
return (await handler(res)).getAllEntries as Omit<
Query['getAllEntries'],
'data'
> & { data: EntryFragment[] }
}

export const find_one_log = async ({ id }: QueryGetOneEntryArgs) => {
const res = await gql(
`query query($id: ID!) {
getOneEntry(id: $id) {
${entry}
...Entry
}
}`,
}
${Entry}
`,
{ id },
)

return (await handler(res)).getOneEntry as Query['getOneEntry']
return (await handler(res)).getOneEntry as EntryFragment
}

export const find_category = async () => {
const res = await gql(
`query query {
getAllCategories {
${category}
...Category
}
}`,
}
${Category}
`,
{},
)

return (await handler(res)).getAllCategories as Query['getAllCategories']
return (await handler(res)).getAllCategories as CategoryFragment[]
}

export const find_one_category = async ({ id }: QueryGetOneCategoryArgs) => {
const res = await gql(
`query query($id: ID!) {
getOneCategory(id: $id) {
${category}
...Category
}
}`,
}
${Category}
`,
{ id },
)

return (await handler(res)).getOneCategory as Query['getOneCategory']
return (await handler(res)).getOneCategory as CategoryFragment
}

export const profile = async () => {
const res = await gql(
`query query {
getCurrentUser {
${user}
...User
}
}`,
}
${User}
`,
{},
)

return (await handler(res)).getCurrentUser as Query['getCurrentUser']
return (await handler(res)).getCurrentUser as UserFragment
}
Loading

0 comments on commit 44d6fa8

Please sign in to comment.