Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
feat: add levels
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtemSBulgakov committed Nov 30, 2024
1 parent d72dd95 commit 8b70817
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 56 deletions.
45 changes: 6 additions & 39 deletions frontend/src/components/mahjong/Mahjong.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { LevelInfo } from '@/components/mahjong/levels.ts'
import type { DotLottieWorker } from '@lottiefiles/dotlottie-react'
import type { Tile as TileT } from './game'
import { DotLottieWorkerReact } from '@lottiefiles/dotlottie-react'
Expand All @@ -7,14 +8,14 @@ import soundTilesMergedDelayed from './assets/bloop_300ms.mp3'
import boomLottie from './assets/boom.lottie?arraybuffer'
import soundTileSelect from './assets/pop-down.mp3'
import { Controls } from './Controls'
import { FieldTemplate, TEMPLATE_2 } from './field-template'
import { FieldTemplate } from './field-template'
import { Game } from './game'
import styles from './Mahjong.module.scss'
import { Tile } from './Tile'

const LOTTIE_SIZE = 300

export function Mahjong() {
export function Mahjong({ level }: { level: LevelInfo }) {
const [tiles, setTiles] = useState<TileT[]>([])
const [selected, setSelected] = useState<TileT | null>(null)
const [mergedAt, setMergedAt] = useState<{ x: number, y: number } | null>(null)
Expand All @@ -27,43 +28,9 @@ export function Mahjong() {

const [game, _] = useState(() => {
const g = Game.random(
FieldTemplate.decode(TEMPLATE_2),
FieldTemplate.decode(level.template),
(a, b) => a === b,
[
'alfa-romeo',
'aston-martin',
'atom',
'audi',
'bentley',
'bmw',
'bugatti',
'byd',
'chevrolet',
'ferrari',
'fiat',
'ford',
'honda',
'hyundai',
'jeep',
'kia',
'lamborghini',
'land-rover',
'lexus',
'lucid-motors',
'mclaren',
'mercedes-benz',
'mini',
'morgan-motor-company',
'nio',
'porsche',
'rivian',
'rolls-royce',
'subaru',
'tesla',
'toyota',
'volkswagen',
'volvo',
],
level.choices,
)
g.onTilesChange = (newTitles) => {
setTiles(newTitles)
Expand Down Expand Up @@ -200,7 +167,7 @@ export function Mahjong() {
platesLeading={[
{
id: 'title',
items: [{ icon: <span className="iconify rotate-180 ph--sign-out" /> }],
items: [{ icon: <span className="iconify ph--sign-out rotate-180" /> }],
clickable: true,
onClick: () => {
alert('not yet :)')
Expand Down
127 changes: 127 additions & 0 deletions frontend/src/components/mahjong/levels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import type { EncodedTemplate } from '@/components/mahjong/field-template.ts'
import { TEMPLATE_1, TEMPLATE_2 } from '@/components/mahjong/field-template.ts'

const allChoices = [
'alfa-romeo',
'aston-martin',
'atom',
'audi',
'bentley',
'bmw',
'bugatti',
'byd',
'chevrolet',
'ferrari',
'fiat',
'ford',
'honda',
'hyundai',
'jeep',
'kia',
'lamborghini',
'land-rover',
'lexus',
'lucid-motors',
'mclaren',
'mercedes-benz',
'mini',
'morgan-motor-company',
'nio',
'porsche',
'rivian',
'rolls-royce',
'subaru',
'tesla',
'toyota',
'volkswagen',
'volvo',
]
type Choice = typeof allChoices[number]

export type LevelInfo = {
id: string
title: string
description: string
template: EncodedTemplate
choices: Choice[]
}

export const levels: LevelInfo[] = [
{
id: '1',
title: 'Уровень 1',
description: 'Самый простой уровень',
template: TEMPLATE_1,
choices: allChoices,
},
{
id: '2',
title: 'Уровень 2',
description: 'Чуть сложнее',
template: TEMPLATE_2,
choices: allChoices,
},
{
id: '3',
title: 'Уровень 3',
description: 'Российский автопром',
template: TEMPLATE_2,
choices: [
'atom',
],
},
{
id: '4',
title: 'Уровень 4',
description: 'Только топовые марки',
template: TEMPLATE_2,
choices: [
'bugatti',
'ferrari',
'lamborghini',
'mclaren',
'porsche',
'rolls-royce',
'tesla',
],
},
{
id: '5',
title: 'Уровень 5',
description: 'Только немецкие марки',
template: TEMPLATE_2,
choices: [
'audi',
'bmw',
'mercedes-benz',
'porsche',
'volkswagen',
],
},
{
id: '6',
title: 'Уровень 6',
description: 'Только китайские марки',
template: TEMPLATE_2,
choices: [
'byd',
'nio',
],
},
{
id: '7',
title: 'Уровень 7',
description: 'Только японские марки',
template: TEMPLATE_2,
choices: [
'honda',
'lexus',
'subaru',
'toyota',
],
},
]

export function getLevelById(id: string | undefined): LevelInfo | undefined {
return levels.find(level => level.id === id)
}
29 changes: 26 additions & 3 deletions frontend/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import { Route as rootRoute } from './routes/__root'
import { Route as TestImport } from './routes/test'
import { Route as PlayImport } from './routes/play'
import { Route as IndexImport } from './routes/index'

// Create/Update Routes
Expand All @@ -22,6 +23,12 @@ const TestRoute = TestImport.update({
getParentRoute: () => rootRoute,
} as any)

const PlayRoute = PlayImport.update({
id: '/play',
path: '/play',
getParentRoute: () => rootRoute,
} as any)

const IndexRoute = IndexImport.update({
id: '/',
path: '/',
Expand All @@ -39,6 +46,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexImport
parentRoute: typeof rootRoute
}
'/play': {
id: '/play'
path: '/play'
fullPath: '/play'
preLoaderRoute: typeof PlayImport
parentRoute: typeof rootRoute
}
'/test': {
id: '/test'
path: '/test'
Expand All @@ -53,36 +67,41 @@ declare module '@tanstack/react-router' {

export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/play': typeof PlayRoute
'/test': typeof TestRoute
}

export interface FileRoutesByTo {
'/': typeof IndexRoute
'/play': typeof PlayRoute
'/test': typeof TestRoute
}

export interface FileRoutesById {
__root__: typeof rootRoute
'/': typeof IndexRoute
'/play': typeof PlayRoute
'/test': typeof TestRoute
}

export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/test'
fullPaths: '/' | '/play' | '/test'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/test'
id: '__root__' | '/' | '/test'
to: '/' | '/play' | '/test'
id: '__root__' | '/' | '/play' | '/test'
fileRoutesById: FileRoutesById
}

export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
PlayRoute: typeof PlayRoute
TestRoute: typeof TestRoute
}

const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
PlayRoute: PlayRoute,
TestRoute: TestRoute,
}

Expand All @@ -97,12 +116,16 @@ export const routeTree = rootRoute
"filePath": "__root.tsx",
"children": [
"/",
"/play",
"/test"
]
},
"/": {
"filePath": "index.tsx"
},
"/play": {
"filePath": "play.tsx"
},
"/test": {
"filePath": "test.tsx"
}
Expand Down
26 changes: 13 additions & 13 deletions frontend/src/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { LevelInfo } from '@/components/mahjong/levels.ts'
import { levels } from '@/components/mahjong/levels.ts'
import { Button } from '@/components/ui/button.tsx'
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card.tsx'
import { createFileRoute, Link } from '@tanstack/react-router'
Expand All @@ -20,34 +22,32 @@ function RouteComponent() {
Сыграйте в увлекательную игру и ближе познакомьтесь с ведущими автомобильными компаниями мира
</div>
<div className="flex flex-row flex-wrap justify-center gap-8">
<LevelCard title="Уровень 1" isUnlocked />
<LevelCard title="Уровень 2" isUnlocked />
<LevelCard title="Уровень 3" isUnlocked={false} />
<LevelCard title="Уровень 4" isUnlocked={false} />
<LevelCard title="Уровень 5" isUnlocked={false} />
<LevelCard title="Уровень 6" isUnlocked={false} />
<LevelCard title="Уровень 7" isUnlocked={false} />
<LevelCard title="Уровень 8" isUnlocked={false} />
<LevelCard title="Уровень 9" isUnlocked={false} />
{levels.map((level, i) => (
<LevelCard key={i} level={level} isUnlocked={i < 2} />
))}
</div>
</div>
</main>
)
}

function LevelCard({ title, isUnlocked }: { title: string, isUnlocked: boolean }) {
function LevelCard({ level, isUnlocked }: { level: LevelInfo, isUnlocked: boolean }) {
return (
<Card className="bg-black bg-opacity-40 backdrop-blur-md transition-all hover:border-emerald-500">
<CardHeader>
<CardTitle>{title}</CardTitle>
<CardDescription>72 кости, Российский автопром</CardDescription>
<CardTitle>{level.title}</CardTitle>
<CardDescription>
72 кости,
{' '}
{level.description}
</CardDescription>
</CardHeader>
<CardContent>
<div className="aspect-video min-w-[300px] rounded-xl bg-gray-900"></div>
</CardContent>
<CardFooter>
<Button asChild disabled={!isUnlocked} variant={isUnlocked ? 'default' : 'secondary'}>
<Link to="/test" className="w-full">
<Link to="/play" search={{ level: level.id }} className="w-full">
{isUnlocked ? 'Играть' : 'Заблокировано'}
</Link>
</Button>
Expand Down
28 changes: 28 additions & 0 deletions frontend/src/routes/play.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { getLevelById } from '@/components/mahjong/levels.ts'
import { Mahjong } from '@/components/mahjong/Mahjong'
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/play')({
component: RouteComponent,
validateSearch: (search: Record<string, unknown>) => {
return {
level: (search.level as string | undefined) || undefined,
}
},
})

function RouteComponent() {
const { level: levelId } = Route.useSearch()

const level = getLevelById(levelId)

if (!level) {
return <div>Invalid level id</div>
}

return (
<div>
<Mahjong level={level} />
</div>
)
}
3 changes: 2 additions & 1 deletion frontend/src/routes/test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { levels } from '@/components/mahjong/levels.ts'
import { Mahjong } from '@/components/mahjong/Mahjong'
import { createFileRoute } from '@tanstack/react-router'

Expand All @@ -8,7 +9,7 @@ export const Route = createFileRoute('/test')({
function RouteComponent() {
return (
<div>
<Mahjong />
<Mahjong level={levels[0]} />
</div>
)
}

0 comments on commit 8b70817

Please sign in to comment.