add labels testing page
This commit is contained in:
42
packages/web/lib/networking/mutations/createLabelMutation.ts
Normal file
42
packages/web/lib/networking/mutations/createLabelMutation.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { gql } from 'graphql-request'
|
||||
import { gqlFetcher } from '../networkHelpers'
|
||||
|
||||
export async function createLabelMutation(
|
||||
name: string,
|
||||
color: string,
|
||||
description?: string
|
||||
): Promise<any | undefined> {
|
||||
const mutation = gql`
|
||||
mutation {
|
||||
createLabel(
|
||||
input: {
|
||||
color: "${color}"
|
||||
name: "${name}"
|
||||
description: "${description}"
|
||||
}
|
||||
) {
|
||||
... on CreateLabelSuccess {
|
||||
label {
|
||||
id
|
||||
name
|
||||
color
|
||||
description
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
... on CreateLabelError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
try {
|
||||
const data = await gqlFetcher(mutation)
|
||||
console.log('created label', data)
|
||||
return data
|
||||
} catch (error) {
|
||||
console.log('createLabelMutation error', error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
34
packages/web/lib/networking/mutations/deleteLabelMutation.ts
Normal file
34
packages/web/lib/networking/mutations/deleteLabelMutation.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { gql } from 'graphql-request'
|
||||
import { gqlFetcher } from '../networkHelpers'
|
||||
|
||||
export async function deleteLabelMutation(
|
||||
labelId: string
|
||||
): Promise<any | undefined> {
|
||||
const mutation = gql`
|
||||
mutation {
|
||||
deleteLabel(id: "${labelId}") {
|
||||
... on DeleteLabelSuccess {
|
||||
label {
|
||||
id
|
||||
name
|
||||
color
|
||||
description
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
... on DeleteLabelError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
try {
|
||||
const data = await gqlFetcher(mutation)
|
||||
console.log('deleted label', data)
|
||||
return data
|
||||
} catch (error) {
|
||||
console.log('deleteLabelMutation error', error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
70
packages/web/lib/networking/queries/useGetLabelsQuery.tsx
Normal file
70
packages/web/lib/networking/queries/useGetLabelsQuery.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import { gql } from 'graphql-request'
|
||||
import useSWR from 'swr'
|
||||
import { publicGqlFetcher } from '../networkHelpers'
|
||||
|
||||
type LabelsQueryResponse = {
|
||||
isValidating: boolean
|
||||
labels: Label[]
|
||||
revalidate: () => void
|
||||
}
|
||||
|
||||
type LabelsResponseData = {
|
||||
labels?: LabelsData
|
||||
}
|
||||
|
||||
type LabelsData = {
|
||||
labels?: unknown
|
||||
}
|
||||
|
||||
export type Label = {
|
||||
id: string
|
||||
name: string
|
||||
color: string
|
||||
description?: string
|
||||
createdAt: Date
|
||||
}
|
||||
|
||||
export function useGetLabelsQuery(): LabelsQueryResponse {
|
||||
const query = gql`
|
||||
query GetLabels {
|
||||
labels {
|
||||
... on LabelsSuccess {
|
||||
labels {
|
||||
id
|
||||
name
|
||||
color
|
||||
description
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
... on LabelsError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const { data, mutate, error, isValidating } = useSWR(query, publicGqlFetcher)
|
||||
|
||||
try {
|
||||
if (data) {
|
||||
const result = data as LabelsResponseData
|
||||
const labels = result.labels?.labels as Label[]
|
||||
return {
|
||||
isValidating,
|
||||
labels,
|
||||
revalidate: () => {
|
||||
mutate()
|
||||
},
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error', error)
|
||||
}
|
||||
return {
|
||||
isValidating: false,
|
||||
labels: [],
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
revalidate: () => {},
|
||||
}
|
||||
}
|
||||
107
packages/web/pages/settings/labels.tsx
Normal file
107
packages/web/pages/settings/labels.tsx
Normal file
@ -0,0 +1,107 @@
|
||||
import { PrimaryLayout } from '../../components/templates/PrimaryLayout'
|
||||
import { Button } from '../../components/elements/Button'
|
||||
import { Box, VStack } from '../../components/elements/LayoutPrimitives'
|
||||
import { toast, Toaster } from 'react-hot-toast'
|
||||
import { useGetLabelsQuery } from '../../lib/networking/queries/useGetLabelsQuery'
|
||||
import { createLabelMutation } from '../../lib/networking/mutations/createLabelMutation'
|
||||
import { deleteLabelMutation } from '../../lib/networking/mutations/deleteLabelMutation'
|
||||
import { useState } from 'react'
|
||||
|
||||
export default function LabelsPage(): JSX.Element {
|
||||
const { labels, revalidate, isValidating } = useGetLabelsQuery()
|
||||
const [name, setName] = useState('')
|
||||
const [color, setColor] = useState('')
|
||||
const [description, setDescription] = useState('')
|
||||
|
||||
async function createLabel(): Promise<void> {
|
||||
const res = await createLabelMutation(name, color, description)
|
||||
if (res) {
|
||||
if (res.createLabel.errorCodes && res.createLabel.errorCodes.length > 0) {
|
||||
toast.error(res.createLabel.errorCodes[0])
|
||||
} else {
|
||||
toast.success('Label created')
|
||||
setName('')
|
||||
setColor('')
|
||||
setDescription('')
|
||||
revalidate()
|
||||
}
|
||||
} else {
|
||||
toast.error('Failed to create label')
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteLabel(id: string): Promise<void> {
|
||||
await deleteLabelMutation(id)
|
||||
revalidate()
|
||||
}
|
||||
|
||||
return (
|
||||
<PrimaryLayout pageTestId="settings-labels-tag">
|
||||
<Toaster />
|
||||
<VStack css={{ mx: '42px' }}>
|
||||
<h2>Create a new label</h2>
|
||||
<form
|
||||
onSubmit={async (e): Promise<void> => {
|
||||
e.preventDefault()
|
||||
await createLabel()
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
placeholder="Name"
|
||||
required
|
||||
value={name}
|
||||
onChange={(event) => {
|
||||
setName(event.target.value)
|
||||
}}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="color"
|
||||
placeholder="Color"
|
||||
required
|
||||
value={color}
|
||||
onChange={(event) => {
|
||||
setColor(event.target.value)
|
||||
}}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="description"
|
||||
placeholder="Description"
|
||||
value={description}
|
||||
onChange={(event) => {
|
||||
setDescription(event.target.value)
|
||||
}}
|
||||
/>
|
||||
<Button type="submit" disabled={isValidating}>
|
||||
Create
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<h2>Labels</h2>
|
||||
{labels &&
|
||||
labels.map((label) => {
|
||||
return (
|
||||
<Box key={label.id}>
|
||||
<form
|
||||
onSubmit={async (e): Promise<void> => {
|
||||
e.preventDefault()
|
||||
await deleteLabel(label.id)
|
||||
}}
|
||||
>
|
||||
<input type="text" value={label.name} disabled />
|
||||
<input type="text" value={label.color} disabled />
|
||||
<input type="text" value={label.description} disabled />
|
||||
<Button type="submit" disabled={isValidating}>
|
||||
Delete
|
||||
</Button>
|
||||
</form>
|
||||
</Box>
|
||||
)
|
||||
})}
|
||||
</VStack>
|
||||
</PrimaryLayout>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user