Skip to content

Commit

Permalink
feat: add "Semesters Summary" view
Browse files Browse the repository at this point in the history
  • Loading branch information
evermake committed Mar 24, 2024
1 parent 8a09e53 commit 9f192f2
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 2 deletions.
1 change: 1 addition & 0 deletions backend/src/bot/handlers/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default handler((composer) => {
composer.use(views.trainingsDaysList)
composer.use(views.trainingsDayTrainings)
composer.use(views.trainingsTraining)
composer.use(views.semestersSummary)

composer.use(commands.start)
composer.use(commands.howgoodami)
Expand Down
2 changes: 2 additions & 0 deletions backend/src/bot/handlers/views/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import settingsLanguage from './settings_language'
import trainingsDaysList from './trainings_days-list'
import trainingsDayTrainings from './trainings_day-trainings'
import trainingsTraining from './trainings_training'
import semestersSummary from './semesters_summary'

// eslint-disable-next-line ts/ban-types
export type View<C extends Context, P = {}> = {
Expand All @@ -20,4 +21,5 @@ export default {
trainingsDaysList,
trainingsDayTrainings,
trainingsTraining,
semestersSummary,
}
16 changes: 14 additions & 2 deletions backend/src/bot/handlers/views/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const VIEW_ID = 'main'

const SettingsButton = makeButton({ id: `${VIEW_ID}:settings` })
const TrainingsButton = makeButton({ id: `${VIEW_ID}:trainings` })
const SemestersButton = makeButton({ id: `${VIEW_ID}:semesters` })

export default {
render: async ctx => (
Expand All @@ -16,6 +17,8 @@ export default {
<keyboard>
<SettingsButton>{ctx.t['Views.Main.Buttons.Settings']}</SettingsButton>
<TrainingsButton>{ctx.t['Views.Main.Buttons.Trainings']}</TrainingsButton>
<br/>
<SemestersButton>{ctx.t['Views.Main.Buttons.Semesters']}</SemestersButton>
</keyboard>
</>
),
Expand All @@ -25,19 +28,28 @@ export default {
composer
.filter(SettingsButton.filter)
.use(async (ctx) => {
ctx.answerCallbackQuery()
await ctx
.edit(ctx.chat!.id, ctx.callbackQuery.message!.message_id)
.to(await views.settings.render(ctx, {}))
ctx.answerCallbackQuery()
})

composer
.filter(TrainingsButton.filter)
.use(async (ctx) => {
ctx.answerCallbackQuery()
await ctx
.edit(ctx.chat!.id, ctx.callbackQuery.message!.message_id)
.to(await views.trainingsDaysList.render(ctx, {}))
ctx.answerCallbackQuery()
})

composer
.filter(SemestersButton.filter)
.use(async (ctx) => {
await ctx
.edit(ctx.chat!.id, ctx.callbackQuery.message!.message_id)
.to(await views.semestersSummary.render(ctx, {}))
ctx.answerCallbackQuery()
})

return composer.middleware()
Expand Down
50 changes: 50 additions & 0 deletions backend/src/bot/handlers/views/semesters_summary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Composer } from 'grammy'
import { makeButton } from '@telegum/grammy-buttons'
import type { View } from '.'
import views from '.'
import type { Ctx } from '~/bot/context'
import { Table } from '~/bot/utils/table'

const VIEW_ID = 'semesters/summary'

const BackButton = makeButton({ id: `${VIEW_ID}:back` })

export default {
render: async (ctx) => {
const summary = await ctx.domain.getSemestersSummary({ telegramId: ctx.from!.id })

const rows = [
['Semester', 'Hours', 'Test'],
...summary.map(({ title, hoursTotal, fitnessTest }) => [
title.length > 8
? `${title.slice(0, 6)}...`
: title,
hoursTotal.toString(),
`${fitnessTest.passed ? '✔' : '✘'} ${fitnessTest.pointsTotal}%`,
]),
]

return (
<>
<Table rows={rows} headingRow />
<keyboard>
<BackButton>{ctx.t['Buttons.Back']}</BackButton>
</keyboard>
</>
)
},
middleware: () => {
const composer = new Composer<Ctx>()

composer
.filter(BackButton.filter)
.use(async (ctx) => {
ctx.answerCallbackQuery()
await ctx
.edit(ctx.chat!.id, ctx.callbackQuery.message!.message_id)
.to(await views.main.render(ctx, {}))
})

return composer.middleware()
},
} satisfies View<Ctx> as View<Ctx>
45 changes: 45 additions & 0 deletions backend/src/bot/utils/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { TgxElement } from '@telegum/tgx'

export type TableProps = {
rows: string[][]
headingRow?: boolean
}

export function Table({
rows,
headingRow = false,
}: TableProps): TgxElement {
if (rows.length === 0) {
return <></>
}

const colCount = rows[0].length
const colLengths = Array.from({ length: colCount }, () => 0)

for (const row of rows) {
for (let i = 0; i < colCount; i++) {
colLengths[i] = Math.max(colLengths[i], row[i].length)
}
}

const table = []

for (const row of rows) {
const cells = row.map((cell, i) => {
const padding = ' '.repeat(colLengths[i] - cell.length)
return `${cell}${padding}`
})
table.push(cells.join(' | '))
}

if (headingRow) {
const divider = colLengths.map(len => '-'.repeat(len)).join('-+-')
table.splice(1, 0, divider)
}

return (
<>
{table.map(row => (<code>{row}<br/></code>))}
</>
)
}
1 change: 1 addition & 0 deletions backend/src/translations/_en.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
'Views.Main.Message': 'Hi! Here is a list of actions:',
'Views.Main.Buttons.Settings': '⚙️ Settings',
'Views.Main.Buttons.Trainings': '⛹️ Classes',
'Views.Main.Buttons.Semesters': '📆 Semesters',

'Views.Settings.Message': 'A list of configurable things:',
'Views.Settings.Buttons.Language': '🌐 Language',
Expand Down

0 comments on commit 9f192f2

Please sign in to comment.