Skip to content

Commit

Permalink
Merge pull request #32 from JasonBoyett/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
JasonBoyett authored Dec 15, 2023
2 parents 3b906a2 + 12d96e9 commit bdb8536
Show file tree
Hide file tree
Showing 17 changed files with 442 additions and 44 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"preact": "^10.15.1",
"react": "^18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.12.0",
"react-p5": "^1.3.35",
"react-router-dom": "^6.14.2",
"shuffle-array": "^1.0.1",
Expand Down
18 changes: 15 additions & 3 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ model User {
wordFlasherSessions WordFlasherSession[]
LetterMatcherSessions LetterMatcherSession[]
GreenDotSessions GreenDotSession[]
NumberGuesserSession NumberGuesserSession[]
BoxFlasherSession BoxFlasherSession[]
PairsSession PairsSession[]
highlightColor Overlay @default(GREY)
lastSchulte String @default(" ")
lastSpeedTest String @default(" ")
Expand All @@ -89,8 +92,8 @@ model User {
lastCubeByThree String @default(" ")
lastNumberGuesser String @default(" ")
lastLetterMatcher String @default(" ")
lastWordPairs String @default(" ")
lastGreenDot String @default(" ")
lastWordPair String @default(" ")
numberGuesserFigures Int @default(4)
font Font @default(sans)
isUsingChecklist Boolean @default(true)
Expand All @@ -100,8 +103,6 @@ model User {
schulteAdvanceCount Int @default(0)
language Language @default(english)
tested Boolean @default(false)
NumberGuesserSession NumberGuesserSession[]
BoxFlasherSession BoxFlasherSession[]
@@index([id])
}
Expand Down Expand Up @@ -208,6 +209,17 @@ model GreenDotSession {
@@index([id])
}

model PairsSession {
id String @unique
userId String
user User @relation(fields: [userId], references: [id])
date DateTime @db.DateTime
time Int
errorCount Int
@@index([id])
}

model SatPassage {
id String @unique
passageText String
Expand Down
8 changes: 6 additions & 2 deletions src/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { useRouter } from 'next/router'
import { useState } from 'react'
import { useClerk } from "@clerk/clerk-react"
import { motion } from 'framer-motion'
import {
IoArrowForwardCircleOutline,
IoArrowBackCircleOutline
} from "react-icons/io5"

export default function Sidebar() {
const [showing, setShowing] = useState<boolean>(false)
Expand Down Expand Up @@ -59,8 +63,8 @@ export default function Sidebar() {
>
{
showing
? '⮈'
: '⮊'
? <IoArrowBackCircleOutline className='text-white'/>
: <IoArrowForwardCircleOutline className='text-white'/>
}
</div>
<div className='grid grid-cols-1 gap-2'>
Expand Down
191 changes: 191 additions & 0 deletions src/components/wordpairs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import { useRouter, type SingletonRouter } from 'next/router'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { uuid } from 'uuidv4'
import { FontProvider } from '~/cva/fontProvider'
import { useStopWatch } from '~/hooks/useStopWatch'
import useUserStore from '~/stores/userStore'
import { api } from '~/utils/api'
import { formatDate, navigateToNextExercise } from '~/utils/helpers'
import type { Font, WordPair } from '~/utils/types'

function useGetProps(total = 18, diffCount = 5) {

const pairs = api.getExcerciseProps.getWordPairs.useQuery({
count: diffCount,
language: "english",
})
const words = api.getExcerciseProps.getRandomWords.useQuery({
number: total - diffCount,
language: "english",
max: 7
})

const result = useMemo(() => {
if (words.isSuccess && pairs.isSuccess) {
return {
words: words.data,
pairs: pairs.data
}
}
else return {
words: undefined,
pairs: undefined
}
}, [pairs, words])

return result
}

type PairsProps = {
diffCount: number
}


export default function WordPairs({ diffCount }: PairsProps) {

const total = 18
const { words, pairs } = useGetProps(total, diffCount)
const user = api.user.getUnique.useQuery()
const { mutate: updateUser } = api.user.setUser.useMutation()
const userStore = useUserStore()
const { mutate: collectSessionData } = api.wordPairSession.setUnique.useMutation()
const stopWatch = useStopWatch()
const router = useRouter()
const foud = useRef(0)
const wrongs = useRef(0)
const font = useRef<Font>('sans')
const [grid, setGrid] = useState<JSX.Element[]>()


function generateGrid() {
if (!pairs || !words) return
const cells = new Array<JSX.Element>()
words.forEach((word) => {
cells.push(generateSame(word))
})
pairs.forEach((pair) => {
cells.push(generateDifferent(pair))
})
stopWatch.start()
return cells.sort(() => Math.random() - 0.5)
}


const handleCellClick = useCallback((answer: 'correct' | 'error') => {
console.log(answer)
if (answer === 'correct') {
foud.current += 1
}
if (answer === 'error') {
wrongs.current += 1
}

if (foud.current === diffCount) tearDown()
console.log('pairsFound', foud.current)
}, [])


function tearDown() {
console.log('teardown')
if (!user) return
if (!userStore.user) return
stopWatch.end()
updateUser({ lastWordPairs: formatDate(new Date()) })
userStore.setUser({
...userStore.user,
lastWordPairs: formatDate(new Date())
})
if (user.data && user.data.isStudySubject) {
collectSessionData({
userId: user.data.id,
errorCount: wrongs.current,
time: stopWatch.getDuration()
})
}
navigateToNextExercise(router as SingletonRouter, user.data ?? userStore.user)
}

function generateSame(word: string) {
return <Cell
different={false}
font={font.current}
word1={word}
word2={word}
id={uuid()}
callback={handleCellClick}
/>
}
function generateDifferent(pair: WordPair) {
return <Cell
different={true}
font={font.current}
word1={pair.primaryWord}
word2={pair.secondaryWord}
id={uuid()}
callback={handleCellClick}
/>
}

useEffect(() => {
if (!user.data) return
font.current = user.data.font
}, [user])

useEffect(() => {
setGrid(() => generateGrid())
}, [words, pairs])

return (
<div
className="grid grid-cols-3 gap-2"
>
{grid}
</div>
)
}

type CellProps = {
font?: Font
different: boolean
word1: string
word2: string
id?: string
callback: (answer: 'correct' | 'error') => void
}

function Cell({ font, different, word1, word2, id, callback }: CellProps) {
const [highlighted, setHighlighted] = useState(false)

function handleClick() {
if (different && !highlighted) {
callback('correct')
setHighlighted(() => true)
}
else if (!different && !highlighted) {
setHighlighted(() => true)
callback('error')
}
}
return (
<FontProvider
font={font}
key={id}
onClick={() => handleClick()}
id={id?.toString() ?? '0'}
className={[
'items-center grid grid-cols-1 rounded-lg text-white',
'md:text-3xl md:p-2',
'text-2xl p-1',
`${highlighted ? (different ? 'bg-white/10' : 'bg-red-500/40') : 'bg-white/20'}`,
'cursor-pointer',
].join(' ')}
>
<div>
{word1}
</div>
<div>
{word2}
</div>
</FontProvider>
)
}
1 change: 1 addition & 0 deletions src/pages/admin/testexercise.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default function Page() {
<NavButton path='/exercises/schultetable?type=7' text='Schulte Table by 7' />
<NavButton path='/exercises/lettermatcher' text='Matching Letters Game' />
<NavButton path='/exercises/greendot' text='Green Dot' />
<NavButton path='/exercises/wordpairs' text='Word Pairs' />
</div>
</div>
</>
Expand Down
18 changes: 18 additions & 0 deletions src/pages/exercises/wordpairs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import dynamic from 'next/dynamic'
import Sidebar from '~/components/sidebar'

const WordPairs = dynamic(() => import('~/components/wordpairs'), { ssr: false })
export default function Page() {
return (
<div className="grid min-h-screen">
<Sidebar />
<div className="flex flex-col items-center">
<center>
<WordPairs
diffCount={5}
/>
</center>
</div>
</div>
)
}
1 change: 0 additions & 1 deletion src/pages/instructions/evennumbers.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useState, useEffect } from 'react'
import type { NextPage } from 'next'
import Head from 'next/head'
import LoadingSpinner from '~/components/loadingspinner'
import { useUserStore } from '~/stores/userStore'
Expand Down
Loading

1 comment on commit bdb8536

@vercel
Copy link

@vercel vercel bot commented on bdb8536 Dec 15, 2023

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.