-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: progress on problems #36
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
b8a3101
style: run prisma format
ykit00 867aac8
feat: Add UserSolvedProblem table and relation to User model
ykit00 caf1014
fix: Programming language name (#31)
Tatehito 2bbcdeb
feat: Add checkpoint problem (#30)
Tatehito a6ee7aa
feat: add create userSolvedProblem action
ykit00 e7e7677
Merge branch 'main' of github.com:exKAZUu-Research/trace-dojo into fe…
ykit00 473d45e
Merge branch 'main' of github.com:exKAZUu-Research/trace-dojo into fe…
ykit00 1bd0511
refactor: fix Addressability directory
ykit00 7defeab
feat: handle complete problem
ykit00 9cd9c33
style: display progress
ykit00 46651a2
feat: display progress and complete status
ykit00 51579c0
style: fix import and tidy up
ykit00 7496165
refactor: renaming function
ykit00 4b9d503
refactor: use server component and Improved performance
ykit00 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
prisma/migrations/20240209123948_create_user_solved_problem_table/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
-- CreateTable | ||
CREATE TABLE "UserSolvedProblem" ( | ||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" DATETIME NOT NULL, | ||
"userId" TEXT NOT NULL, | ||
"courseId" TEXT NOT NULL, | ||
"programId" TEXT NOT NULL, | ||
"languageId" TEXT NOT NULL, | ||
CONSTRAINT "UserSolvedProblem_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
'use client'; | ||
|
||
import { | ||
Box, | ||
Heading, | ||
VStack, | ||
Accordion, | ||
AccordionItem, | ||
AccordionButton, | ||
AccordionIcon, | ||
AccordionPanel, | ||
Select, | ||
Table, | ||
TableContainer, | ||
Thead, | ||
Tbody, | ||
Tr, | ||
Td, | ||
Th, | ||
Flex, | ||
} from '@chakra-ui/react'; | ||
import Image from 'next/image'; | ||
import NextLink from 'next/link'; | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { | ||
courseIdToProgramIdLists, | ||
languageIdToName, | ||
languageIds, | ||
programIdToName, | ||
} from '../../../../problems/problemData'; | ||
import { getLanguageIdFromSessionStorage, setLanguageIdToSessionStorage } from '../../../lib/SessionStorage'; | ||
|
||
export const Course: React.FC<{ | ||
courseId: string; | ||
userSolvedProblems: { programId: string; languageId: string }[]; | ||
}> = ({ courseId, userSolvedProblems }) => { | ||
const [selectedLanguageId, setSelectedLanguageId] = useState(''); | ||
|
||
const SPECIFIED_COMPLETION_COUNT = 2; | ||
|
||
useEffect(() => { | ||
setSelectedLanguageId(getLanguageIdFromSessionStorage()); | ||
}, []); | ||
|
||
const handleSelectLanguage = (event: React.ChangeEvent<HTMLSelectElement>): void => { | ||
const inputValue = event.target.value; | ||
setLanguageIdToSessionStorage(inputValue); | ||
setSelectedLanguageId(inputValue); | ||
}; | ||
|
||
const countUserSolvedProblems = (programId: string, languageId: string): number => { | ||
return userSolvedProblems.filter( | ||
(userSolvedProblem) => userSolvedProblem.programId === programId && userSolvedProblem.languageId === languageId | ||
).length; | ||
}; | ||
|
||
return ( | ||
<main> | ||
<Heading as="h1" marginBottom="4"> | ||
Lessons | ||
</Heading> | ||
<Select | ||
marginBottom="4" | ||
maxW="300" | ||
placeholder="Select language" | ||
value={selectedLanguageId} | ||
onChange={(e) => handleSelectLanguage(e)} | ||
> | ||
{languageIds.map((languageId) => ( | ||
<option key={languageId} value={languageId}> | ||
{languageIdToName[languageId]} | ||
</option> | ||
))} | ||
</Select> | ||
<VStack align="stretch"> | ||
{courseIdToProgramIdLists[courseId].map((programIds, iLesson) => ( | ||
<Box key={iLesson}> | ||
<Accordion allowToggle> | ||
<AccordionItem> | ||
<AccordionButton> | ||
<Box flex="1" textAlign="left"> | ||
第{iLesson + 1}回 | ||
</Box> | ||
<AccordionIcon /> | ||
</AccordionButton> | ||
<AccordionPanel pb={4}> | ||
<TableContainer> | ||
<Table> | ||
<Thead> | ||
<Tr> | ||
<Th textAlign="left" width="50%"> | ||
プログラム | ||
</Th> | ||
<Th align="left" width="50%"> | ||
進捗 | ||
</Th> | ||
</Tr> | ||
</Thead> | ||
<Tbody> | ||
{programIds.map((programId) => ( | ||
<Tr key={programId}> | ||
<Td> | ||
<NextLink passHref href={`${courseId}/programs/${programId}`}> | ||
{programIdToName[programId]} | ||
</NextLink> | ||
</Td> | ||
<Td> | ||
<Flex> | ||
<p> | ||
{countUserSolvedProblems(programId, selectedLanguageId)} /{' '} | ||
{SPECIFIED_COMPLETION_COUNT} | ||
</p> | ||
{countUserSolvedProblems(programId, selectedLanguageId) >= | ||
SPECIFIED_COMPLETION_COUNT && ( | ||
<Box h={4} ml={2} position={'relative'} w={4}> | ||
<Image fill alt="完了の王冠" src="/crown.png" /> | ||
</Box> | ||
)} | ||
</Flex> | ||
</Td> | ||
</Tr> | ||
))} | ||
</Tbody> | ||
</Table> | ||
</TableContainer> | ||
</AccordionPanel> | ||
</AccordionItem> | ||
</Accordion> | ||
</Box> | ||
))} | ||
</VStack> | ||
</main> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,90 +1,30 @@ | ||
'use client'; | ||
|
||
import { | ||
Box, | ||
Heading, | ||
OrderedList, | ||
ListItem, | ||
VStack, | ||
Accordion, | ||
AccordionItem, | ||
AccordionButton, | ||
AccordionIcon, | ||
AccordionPanel, | ||
Select, | ||
} from '@chakra-ui/react'; | ||
import type { NextPage } from 'next'; | ||
import NextLink from 'next/link'; | ||
import React, { useEffect, useState } from 'react'; | ||
import { redirect } from 'next/navigation'; | ||
|
||
import { prisma } from '../../../../infrastructures/prisma'; | ||
import { getNullableSessionOnServer } from '../../../../utils/session'; | ||
import { fetchUserSolvedProblems } from '../../../lib/actions'; | ||
|
||
import { | ||
courseIdToProgramIdLists, | ||
languageIdToName, | ||
languageIds, | ||
programIdToName, | ||
} from '../../../../problems/problemData'; | ||
import { getLanguageIdFromSessionStorage, setLanguageIdToSessionStorage } from '../../../lib/SessionStorage'; | ||
import { Course } from './Course'; | ||
|
||
const CoursePage: NextPage<{ params: { courseId: string } }> = ({ params }) => { | ||
const [selectedLanguageId, setSelectedLanguageId] = useState(''); | ||
const CoursePage: NextPage<{ params: { courseId: string } }> = async ({ params }) => { | ||
const { session } = await getNullableSessionOnServer(); | ||
const user = | ||
session && | ||
(await prisma.user.findUnique({ | ||
where: { | ||
id: session.getUserId(), | ||
}, | ||
})); | ||
|
||
useEffect(() => { | ||
setSelectedLanguageId(getLanguageIdFromSessionStorage()); | ||
}, []); | ||
if (!user) { | ||
return redirect('/auth'); | ||
} | ||
|
||
const handleSelectLanguage = (event: React.ChangeEvent<HTMLSelectElement>): void => { | ||
const inputValue = event.target.value; | ||
setLanguageIdToSessionStorage(inputValue); | ||
setSelectedLanguageId(inputValue); | ||
}; | ||
const courseId = params.courseId; | ||
const userSolvedProblems = await fetchUserSolvedProblems(user.id, courseId); | ||
|
||
return ( | ||
<main> | ||
<Heading as="h1" marginBottom="4"> | ||
Lessons | ||
</Heading> | ||
<Select | ||
marginBottom="4" | ||
maxW="300" | ||
placeholder="Select language" | ||
value={selectedLanguageId} | ||
onChange={(e) => handleSelectLanguage(e)} | ||
> | ||
{languageIds.map((languageId) => ( | ||
<option key={languageId} value={languageId}> | ||
{languageIdToName[languageId]} | ||
</option> | ||
))} | ||
</Select> | ||
<VStack align="stretch"> | ||
{courseIdToProgramIdLists[params.courseId].map((programIds, iLesson) => ( | ||
<Box key={iLesson}> | ||
<Accordion allowToggle> | ||
<AccordionItem> | ||
<AccordionButton> | ||
<Box flex="1" textAlign="left"> | ||
第{iLesson + 1}回 | ||
</Box> | ||
<AccordionIcon /> | ||
</AccordionButton> | ||
<AccordionPanel pb={4}> | ||
<OrderedList> | ||
{programIds.map((programId) => ( | ||
<ListItem key={programId}> | ||
<NextLink passHref href={`/programs/${programId}`}> | ||
{programIdToName[programId]} | ||
</NextLink> | ||
</ListItem> | ||
))} | ||
</OrderedList> | ||
</AccordionPanel> | ||
</AccordionItem> | ||
</Accordion> | ||
</Box> | ||
))} | ||
</VStack> | ||
</main> | ||
); | ||
return <Course courseId={params.courseId} userSolvedProblems={userSolvedProblems} />; | ||
}; | ||
|
||
export default CoursePage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
programIdやcourseIdはハードコーディングしてるから、問題IDやコースIDの変更は基本できない(やる場合はUserSolvedProblemのレコードも更新する)のは気をつけないといけないですね・・・💡
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ですね! どこかでDBを使用するように改善する余地もあるかもしれません!