Skip to content

Commit

Permalink
Merge pull request #2587 from flacial/feat/flag-exercise
Browse files Browse the repository at this point in the history
feat(component): Create ExerciesReportCard
  • Loading branch information
flacial authored Dec 10, 2022
2 parents 1309f26 + 65a6b2a commit b105d42
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 0 deletions.
23 changes: 23 additions & 0 deletions __tests__/__snapshots__/storyshots.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6660,6 +6660,29 @@ a = a + 10
</section>
`;

exports[`Storyshots Components/ExerciseReportCard Basic 1`] = `
<div>
<p>
Leave the description empty and try to submit to display success message
</p>
<div
className=""
>
<button
className="btn newButton container__reportBtn borderless"
onClick={[Function]}
style={
Object {
"color": "mute",
}
}
>
Report a problem
</button>
</div>
</div>
`;

exports[`Storyshots Components/FilterButtons Basic 1`] = `
<div
className="d-flex flex-row"
Expand Down
66 changes: 66 additions & 0 deletions components/ExerciseReportCard/ExerciseReportCard.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react'
import ExerciseReportCard from './index'
import { render, screen } from '@testing-library/react'
import { MockedProvider } from '@apollo/client/testing'
import FLAG_EXERCISE from '../../graphql/queries/flagExercise'
import userEvent from '@testing-library/user-event'

// Imported to be able to use expect(...).toBeInTheDocument()
import '@testing-library/jest-dom'

const mocks = [
{
request: {
query: FLAG_EXERCISE,
variables: {
id: 1,
flagReason: 'Bad exercise'
}
},
result: {
data: {
flagExercise: {
id: 1
}
}
}
}
]

const reportBtn = 'Report a problem'

describe('ExerciseReportCard Component', () => {
it('Should submit an issue successfully', async () => {
expect.assertions(1)

render(
<MockedProvider mocks={mocks}>
<ExerciseReportCard exerciseId={1} answerShown={true} />
</MockedProvider>
)

await userEvent.click(screen.getByText(reportBtn))

await userEvent.type(screen.getByTestId('textbox'), 'Bad exercise')
await userEvent.click(screen.getByText('Submit issue'))

expect(
await screen.findByText('Reported a mistake in this exercise')
).toBeInTheDocument()
})

it('Should cancel the report', async () => {
expect.assertions(1)

render(
<MockedProvider mocks={mocks}>
<ExerciseReportCard exerciseId={1} answerShown={false} />
</MockedProvider>
)

await userEvent.click(screen.getByText(reportBtn))
await userEvent.click(screen.getByText('Cancel'))

expect(await screen.findByText(reportBtn)).toBeInTheDocument()
})
})
141 changes: 141 additions & 0 deletions components/ExerciseReportCard/ExerciseReportCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { ApolloError } from '@apollo/client'
import React, { useState } from 'react'
import { DISCORD_PATH } from '../../constants'
import { FlagExerciseMutation, useFlagExerciseMutation } from '../../graphql'
import styles from './exerciseReportCard.module.scss'
import { MdInput } from '../MdInput'
import NavLink from '../NavLink'
import QueryInfo from '../QueryInfo'
import { Button } from '../theme/Button'
import btnStyles from '../../scss/button.module.scss'

type BodyProps = {
description: string
loading: boolean
data?: null | FlagExerciseMutation
error?: ApolloError
setDescription: (str: string) => void
flagExercise: () => void
setReportMode: (mode: boolean) => void
}

const Body = ({
description,
loading,
error,
data,
setDescription,
flagExercise,
setReportMode
}: BodyProps) => (
<div className={styles.container}>
<h5>Report a mistake in this exercise</h5>
<p>Remember to double check your answer. Thanks for your help!</p>
<p>
Alternatively, you can{' '}
<NavLink hoverUnderline path={DISCORD_PATH}>
report any technical problems
</NavLink>{' '}
you might be experiencing.
</p>
<label htmlFor="description" className="mb-2">
Description of issue:
</label>
<MdInput
onChange={(v: string) => setDescription(v)}
value={description}
placeHolder="Describe the mistake here..."
/>
<div className={styles.container__btns__container}>
{loading || error ? (
<QueryInfo
data={data}
loading={loading}
error={error?.message || ''}
texts={{
loading: 'Submitting the issue...',
data: 'Thanks for reporting!',
error: 'Oops, something went wrong.'
}}
/>
) : (
<>
<Button
border
outline
btnType="info"
color="info"
onClick={() => flagExercise()}
>
Submit issue
</Button>
<Button
outline
btnType="info"
color="info"
onClick={() => setReportMode(false)}
>
Cancel
</Button>
</>
)}
</div>
</div>
)

type Props = {
exerciseId: number
answerShown: boolean
}

const ExerciseReportCard = ({ exerciseId, answerShown }: Props) => {
const [reportMode, setReportMode] = useState(false)
const [description, setDescription] = useState('')
const [flagExercise, { data, loading, error }] = useFlagExerciseMutation({
variables: {
id: exerciseId,
flagReason: description
}
})

const marginOnExpand = answerShown ? 'mt-5' : ''

if (data && !loading) {
return (
<div className={`${styles.container} ${marginOnExpand}`}>
<h6>Reported a mistake in this exercise</h6>
<p className="mb-0">
We appreciate your input. We will shortly investigate the problem that
has been reported.
</p>
</div>
)
}

return (
<div className={marginOnExpand}>
{reportMode ? (
<Body
data={data}
loading={loading}
error={error}
description={description}
setDescription={setDescription}
flagExercise={flagExercise}
setReportMode={setReportMode}
/>
) : (
<Button
className={`${btnStyles.newButton} ${styles.container__reportBtn}`}
onClick={() => setReportMode(true)}
outline
color="mute"
>
Report a problem
</Button>
)}
</div>
)
}

export default ExerciseReportCard
28 changes: 28 additions & 0 deletions components/ExerciseReportCard/exerciseReportCard.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@use '../../scss/colors.module.scss';

.container {
max-width: 400px;
background-color: hsl(0, 0%, 96%);
padding: 20px;
border: 1px solid hsl(0, 0%, 84%);
border-radius: 10px;
}

.container__reportBtn {
font-size: 12px;
background-color: transparent;
padding: 0;

&:hover {
color: colors.$bg-green;
background-color: transparent;
box-shadow: unset;
}
}

.container__btns__container {
display: grid;
row-gap: 8px;
margin-top: 18px;
width: 100%;
}
1 change: 1 addition & 0 deletions components/ExerciseReportCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ExerciseReportCard'
41 changes: 41 additions & 0 deletions stories/components/ExerciseReportCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { MockedProvider } from '@apollo/client/testing'
import React from 'react'
import ExerciseReportCard from '../../components/ExerciseReportCard'
import FLAG_EXERCISE from '../../graphql/queries/flagExercise'

export default {
component: ExerciseReportCard,
title: 'Components/ExerciseReportCard'
}

export const Basic = () => {
return (
<div>
<p>
Leave the description empty and try to submit to display success message
</p>
<MockedProvider
mocks={[
{
request: {
query: FLAG_EXERCISE,
variables: {
id: 1,
flagReason: ''
}
},
result: {
data: {
flagExercise: {
id: 1
}
}
}
}
]}
>
<ExerciseReportCard exerciseId={1} answerShown={false} />
</MockedProvider>
</div>
)
}

1 comment on commit b105d42

@vercel
Copy link

@vercel vercel bot commented on b105d42 Dec 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.