Skip to content

Commit

Permalink
feat: settings page
Browse files Browse the repository at this point in the history
  • Loading branch information
garrappachc committed Aug 8, 2024
1 parent 19f8c9f commit 8908822
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/database/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { GameLogsModel } from './models/game-logs.model'
import type { GameModel } from './models/game.model'
import type { MapPoolEntry } from './models/map-pool-entry.model'
import type { OnlinePlayerModel } from './models/online-player.model'
import type { PlayerPreferencesModel } from './models/player-preferences.model'
import type { PlayerModel } from './models/player.model'
import type { QueueFriendshipModel } from './models/queue-friendship.model'
import type { QueueMapOptionModel } from './models/queue-map-option.model'
Expand All @@ -22,6 +23,7 @@ export const collections = {
maps: database.collection<MapPoolEntry>('maps'),
onlinePlayers: database.collection<OnlinePlayerModel>('onlineplayers'),
players: database.collection<PlayerModel>('players'),
playerPreferences: database.collection<PlayerPreferencesModel>('playerpreferences'),
queueFriends: database.collection<QueueFriendshipModel>('queue.friends'),
queueSlots: database.collection<QueueSlotModel>('queue.slots'),
queueState: database.collection<QueueStateModel>('queue.state'),
Expand Down
9 changes: 9 additions & 0 deletions src/database/models/player-preferences.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ObjectId } from 'mongodb'

// TODO remove, move to PlayerModel
export interface PlayerPreferencesModel {
player: ObjectId
preferences: {
soundVolume?: string
}
}
11 changes: 11 additions & 0 deletions src/html/components/icons/icon-volume.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { makeIcon } from './make-icon'

export const IconVolume = makeIcon(
'volume',
<>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M15 8a5 5 0 0 1 0 8" />
<path d="M17.7 5a9 9 0 0 1 0 14" />
<path d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a.8 .8 0 0 1 1.5 .5v14a.8 .8 0 0 1 -1.5 .5l-3.5 -4.5" />
</>,
)
1 change: 1 addition & 0 deletions src/html/components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ export { IconSettings } from './icon-settings'
export { IconStars } from './icon-stars'
export { IconUserCircle } from './icon-user-circle'
export { IconUserScan } from './icon-user-scan'
export { IconVolume } from './icon-volume'
export { IconX } from './icon-x'
53 changes: 53 additions & 0 deletions src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,56 @@ dialog::backdrop {
}
}
}

input[type='range'] {
appearance: none;
background: transparent;

&::-webkit-slider-thumb {
appearance: none;
}

&:focus {
outline: none;
}

&::-ms-track {
width: 100%;
cursor: pointer;

background: transparent;
border-color: transparent;
color: transparent;
}

&::-webkit-slider-thumb,
&::-moz-range-thumb {
height: 18px;
width: 18px;
border-radius: 50%;
background-color: theme('colors.accent.DEFAULT');
cursor: pointer;
border: none;
}

&:hover::-webkit-slider-thumb,
&:hover::-moz-range-thumb {
background-color: darken(theme('colors.accent.DEFAULT'), 10%);
}

&:focus::-webkit-slider-thumb,
&:focus::-moz-range-thumb {
border: 1px solid theme('colors.accent.DEFAULT');
outline: 3px solid theme('colors.accent.DEFAULT');
outline-offset: 0.125rem;
}

&::-webkit-slider-runnable-track,
&::-moz-range-track {
width: 100%;
height: 8px;
cursor: pointer;
background-color: theme('colors.abru.light.5');
border-radius: 4px;
}
}
43 changes: 43 additions & 0 deletions src/players/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { collections } from '../database/collections'
import { PlayerRole } from '../database/models/player.model'
import { update } from './update'
import { Tf2ClassName } from '../shared/types/tf2-class-name'
import { PlayerSettingsPage } from './views/html/player-settings.page'

export default fp(
// eslint-disable-next-line @typescript-eslint/require-await
Expand Down Expand Up @@ -195,6 +196,48 @@ export default fp(
reply.status(200).html(await EditPlayerBansPage({ player, user: req.user! }))
},
)
.get(
'/settings',
{
config: {
authenticate: true,
},
},
async (req, reply) => {
reply.status(200).html(await PlayerSettingsPage({ user: req.user! }))
},
)
.post(
'/settings',
{
config: {
authenticate: true,
},
schema: {
body: z.object({
soundVolume: z.coerce.number().min(0).max(1),
}),
},
},
async (req, reply) => {
const player = await collections.players.findOne({ steamId: req.user!.player.steamId })
if (!player) {
throw new Error(`player not found: ${req.user!.player.steamId}`)
}
const preferences =
(await collections.playerPreferences.findOne({ player: player._id }))?.preferences ?? {}
preferences.soundVolume = req.body.soundVolume.toString()
await collections.playerPreferences.updateOne(
{ player: player._id },
{
$set: {
preferences,
},
},
)
await reply.redirect(`/settings`)
},
)
},
{ name: 'players routes' },
)
50 changes: 50 additions & 0 deletions src/players/views/html/player-settings.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Layout } from '../../../html/layout'
import type { User } from '../../../auth/types/user'
import { NavigationBar } from '../../../html/components/navigation-bar'
import { Page } from '../../../html/components/page'
import { IconVolume } from '../../../html/components/icons'
import { collections } from '../../../database/collections'

export async function PlayerSettingsPage(props: { user: User }) {
const player = await collections.players.findOne({ steamId: props.user.player.steamId })
const preferences = await collections.playerPreferences.findOne({ player: player!._id })
const soundVolume = preferences?.preferences.soundVolume ?? '1.0'

return (
<Layout title="Settings">
<NavigationBar user={props.user} />
<Page>
<div class="container mx-auto">
<form action="" method="post">
<div class="bg-abru-dark-25 rounded-lg flex-1 p-[24px] text-abru-light-75 font-normal flex flex-col gap-4">
<h4 class="font-bold text-[24px]">Preferences</h4>

<div class="flex flex-col">
<label for="notification-sound-volume">Notification sound volume</label>
<div class="flex flex-row items-center gap-2">
<IconVolume />
<input
type="range"
min="0"
max="1"
step="0.1"
value={soundVolume}
id="notification-sound-volume"
name="soundVolume"
class="w-[360px]"
></input>
</div>
</div>

<div class="flex">
<button type="submit" class="button button--accent mt-6">
Save
</button>
</div>
</div>
</form>
</div>
</Page>
</Layout>
)
}

0 comments on commit 8908822

Please sign in to comment.