Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nyala 363 ask a question #121

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Ask a question
alaa-yahia committed Jun 20, 2021
commit fc2765bb52474ecbffa9530e2d12d8cf98ef4f40
66 changes: 66 additions & 0 deletions src/components/Courses/LectureQuestion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useState } from 'react'
import { toast } from 'react-toastify'
import { useTranslation } from 'react-i18next'
import { Question } from '../../types/api.types'
import { updateQuestion, getQuestions } from '../../services/api'

type Props = {
question: Question
isLoggedIn: boolean
updateQuestionsList: (data: Question[]) => void
}

const LectureQuestions: React.FC<Props> = ({
question,
isLoggedIn,
updateQuestionsList,
}) => {
const { t } = useTranslation()
const { id, text, replies } = question

const [replyInput, setReplyInput] = useState('')

const handleSubmit = async () => {
try {
await updateQuestion(id, {
replies: [{ reply: replyInput }, ...replies],
})
const data = await getQuestions()
updateQuestionsList(data)
toast.success('Reply submitted successfully')
} catch (err) {
const message = err.message.match(/(403|400)/)
? 'errors.invalid_auth'
: 'errors.generic'
toast.error(t(message))
}
}

return (
<div>
<div>{text}</div>

<div className="ml-10">
{isLoggedIn && (
<div>
<input
type="text"
className="px-2 bg-gray-100 text-gray-700 border border-gray-300 rounded block appearance-none placeholder-gray-500 focus:outline-none focus:bg-white"
placeholder="Your Reply"
value={replyInput}
onChange={e => setReplyInput(e.target.value)}
/>
<button type="submit" onClick={handleSubmit}>
Submit
</button>
</div>
)}
{replies.map(reply => (
<div>{reply.reply}</div>
))}
</div>
</div>
)
}

export default LectureQuestions
74 changes: 74 additions & 0 deletions src/components/Courses/LectureQuestions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useState } from 'react'
import { toast } from 'react-toastify'
import { useTranslation } from 'react-i18next'
import { orderBy } from 'lodash'
import { addQuestion, getQuestions } from '../../services/api'
import { Question } from '../../types/api.types'
import LectureQuestion from './LectureQuestion'

type Props = {
questions: Question[]
isLoggedIn: boolean
lectureId: number
}

const LectureQuestions: React.FC<Props> = ({
questions,
isLoggedIn,
lectureId,
}) => {
const { t } = useTranslation()
const [questionInput, setQuestionInput] = useState('')
const [questionsList, setQuestionList] = useState(questions)

const updateQuestionsList = data => {
setQuestionList(data)
}

const handleSubmit = async () => {
try {
await addQuestion({
text: questionInput,
replies: [],
lecture: lectureId,
})
const data = await getQuestions()
updateQuestionsList(data)
toast.success('Question submitted successfully')
} catch (err) {
const message = err.message.match(/(403|400)/)
? 'errors.invalid_auth'
: 'errors.generic'
toast.error(t(message))
}
}

return (
<div>
<h3>Questions</h3>
{isLoggedIn && (
<div>
<input
type="text"
className="px-2 bg-gray-100 text-gray-700 border border-gray-300 rounded block appearance-none placeholder-gray-500 focus:outline-none focus:bg-white"
placeholder="Your Question"
value={questionInput}
onChange={e => setQuestionInput(e.target.value)}
/>
<button type="submit" onClick={handleSubmit}>
Submit
</button>
</div>
)}
{questionsList.map(question => (
<LectureQuestion
question={question}
isLoggedIn={isLoggedIn}
updateQuestionsList={updateQuestionsList}
/>
))}
</div>
)
}

export default LectureQuestions
21 changes: 21 additions & 0 deletions src/services/api.ts
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import {
UserSubscribeToMailingList,
UserPrToReviewData,
CourseRating,
Question,
} from '../types/api.types'

const axiosInstance = () => {
@@ -100,6 +101,26 @@ export const subscribeToMailingList = async (
return data
}

export const getQuestions = async (): Promise<Question[]> => {
const { data } = await axiosInstance().get(`/questions`)
return data
}

export const addQuestion = async (
values: Partial<Question>
): Promise<Question> => {
const { data } = await axiosInstance().post(`/questions`, values)
return data
}

export const updateQuestion = async (
questionId: number,
values: Partial<Question>
): Promise<Question> => {
const { data } = await axiosInstance().put(`/questions/${questionId}`, values)
return data
}

/**
* Upload file to strapi media
* @param {*} file The file object
18 changes: 17 additions & 1 deletion src/templates/LectureView/index.tsx
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ import CourseCard from '../../components/Courses/CourseCard'
import { AuthContext } from '../../contexts/AuthContext'
import { ALLOWED_LECTURES_WHEN_NOT_LOGGED_IN } from '../../common/constants'
import { Course, Lecture } from '../../types/api.types'
import LectureQuestions from '../../components/Courses/LectureQuestions'

type LectureViewProps = {
data: {
@@ -28,13 +29,14 @@ type LectureViewProps = {
const LectureView: React.FC<LectureViewProps> = ({ data, location }) => {
const { t } = useTranslation()
const { strapiLecture, strapiCourse, relatedCourses } = data
console.log(strapiLecture, 'lop')
const sortedLectures = orderBy(strapiCourse.lectures, 'position', 'asc')
const lecture = !strapiLecture ? sortedLectures[0] : strapiLecture
const { isLoggedIn, currentUser } = useContext(AuthContext)
if (!strapiCourse) {
return <div />
}
const { url, title: lectureTitle, position, strapiId } = lecture
const { url, title: lectureTitle, position, strapiId, questions } = lecture
const {
title: courseTitle,
slug,
@@ -144,6 +146,13 @@ const LectureView: React.FC<LectureViewProps> = ({ data, location }) => {
courseStrapiId={courseStrapiId}
/>
</div>
<div>
<LectureQuestions
questions={questions}
isLoggedIn={isLoggedIn}
lectureId={strapiId}
/>
</div>
</div>
</div>
{relatedCourses.edges.length !== 0 && (
@@ -191,6 +200,13 @@ export const pageQuery = graphql`
created_at
title
position
questions {
id
text
replies {
reply
}
}
}

strapiCourse(slug: { eq: $courseSlug }) {
14 changes: 13 additions & 1 deletion src/types/api.types.ts
Original file line number Diff line number Diff line change
@@ -114,8 +114,19 @@ export type Resource = {
type: ResourceType
}

export type Lecture = {
export type Reply = {
reply: string
}

export type Question = {
id: number
text: string
replies: Reply[]
lecture: number
}

export type Lecture = {
id: string
strapiId: number
title: string
description?: string
@@ -124,6 +135,7 @@ export type Lecture = {
position: number
slug: string
created_at: string
questions: Question[]
}

export type Course = {