Courtio - {{ selectedClubName }} Dashboard
{{ userRole }}

Bookings

Calendar view of all bookings for your club.

{{ bookingStats.count }} bookings {{ bookingStats.playtomic }} playtomic {{ bookingStats.hours }} h {{ bookingStats.occupancy }} h/court

Loading...

Loading club data...

Time
{{ court.name }}

{{ bookingTypeLabel(selectedBooking) }}

Court {{ selectedBooking.court?.name || '—' }}
Date {{ formatDate(selectedBooking.date) }}
Duration {{ selectedBooking.duration }} min
Level {{ selectedBooking.minLevel ?? '—' }} - {{ selectedBooking.maxLevel ?? '—' }}
Comments {{ selectedBooking.comments }}
Created
Total Price {{ (selectedBooking.totalPrice / 100).toFixed(2) }} {{ selectedBooking.currency || '' }}
Score {{ selectedBooking.score1 ?? '—' }} - {{ selectedBooking.score2 ?? '—' }}

Players

{{ p.firstName }} {{ p.lastName }} {{ playerPaid(selectedBooking, p) ? 'Paid' : 'Unpaid' }}

{{ bookingModal.mode === 'create' ? 'Create Booking' : 'Edit Booking' }}

{{ bookingModal.players[i - 1].firstName }} {{ bookingModal.players[i - 1].lastName }} ×
{{ bookingModalError }}

Unsettled payments — {{ bookingsDate }}

All settled for this day.

Time Court Player Type Action
{{ formatTime(p.bookingDate) }} {{ p.courtName }} {{ p.playerFirstName ? p.playerFirstName + ' ' + p.playerLastName : (p.bookingComments ? p.bookingComments.replace(' - playtomic', '') : 'Blocking') }} Match Blocking Event Training Other Saving...

Payments

Payment history for your club.

Loading...

No past due payments.

Date Court Player Type Action
{{ formatDate(p.bookingDate) }} {{ p.courtName }} {{ p.playerFirstName ? p.playerFirstName + ' ' + p.playerLastName : (p.bookingComments ? p.bookingComments.replace(' - playtomic', '') : 'Blocking') }} Playtomic Match Blocking Event Training Other Saving...

Loading...

No upcoming payments.

Date Court Player Type Action
{{ formatDate(p.bookingDate) }} {{ p.courtName }} {{ p.playerFirstName ? p.playerFirstName + ' ' + p.playerLastName : (p.bookingComments ? p.bookingComments.replace(' - playtomic', '') : 'Blocking') }} Playtomic Match Blocking Event Training Other Saving...
Total: {{ paymentsTotal }}

Loading...

No payments found.

Booking date Court Player Amount Type Marked by Paid at Action
{{ formatDate(p.bookingDate) }} {{ p.courtName }} {{ p.playerFirstName ? p.playerFirstName + ' ' + p.playerLastName : (p.bookingComments ? p.bookingComments.replace(' - playtomic', '') : '—') }} {{ p.paymentMethod === 'vip' ? '0.00 ' + (p.currency || 'RON').toUpperCase() : (p.amount ? (p.amount / 100).toFixed(2) + ' ' + (p.currency || '').toUpperCase() : '—') }} Refund Playtomic Paid 📱 Manual 💵 Manual 💳 VIP 👑 Manual {{ p.markedBy || '—' }} {{ formatDate(p.paidAt) }}

Players

Players who have bookings at your club.

{{ playersTotal }} player{{ playersTotal !== 1 ? 's' : '' }}

Edit Player

WhatsApp
{{ playerSaveMsg }}
{{ playerSaveError }}

Loading...

{{ playersSearch ? 'No players match your search.' : 'No players found.' }}

Player {{ sortArrow('name') }} User ID Phone Level Points {{ sortArrow('points') }} Type Matches {{ sortArrow('matchCount') }} Matches (30d) {{ sortArrow('matchCount30d') }} Last Active {{ sortArrow('lastPlayed') }}
{{ (p.firstName?.[0] || '') + (p.lastName?.[0] || '') }}
{{ p.firstName }} {{ p.lastName }}
{{ p.gender === 0 ? 'Male' : 'Female' }}
{{ p.userId || '—' }} {{ p.phone || '—' }} {{ playerLevel(p.points) }} {{ p.points }} {{ playerTypeName(p.type) }} {{ p.matchCount }} {{ p.matchCount30d }} {{ formatDateShort(p.lastPlayed) }}
Page {{ playersPage }} of {{ playersTotalPages }}

Club Details

Edit your club information and manage courts.

Loading...

{{ clubSaveMsg }}
{{ clubSaveError }}

Club Images

{{ clubImageError }}
Club logo
Uploading...

Courts

{{ court.name }}
No courts added yet.

Club Prices

Manage court pricing rules.

{{ editingTierKey ? 'Edit Price Tier' : 'Add Price Tier' }}

{{ clubCurrency }}
{{ priceTierError }}
{{ priceTierSuccess }}

Loading...

No prices configured yet.

Courts Days Hours Price / 30 min Price / hour
{{ g.courtIds.map(id => courtName(id)).join(', ') }} {{ g.days.map(d => dayName(d)).join(', ') }} {{ formatHour(g.startHour) }} - {{ formatHour(g.endHour) }} {{ (g.price / 100).toFixed(2) }} {{ clubCurrency }} {{ (g.price * 2 / 100).toFixed(2) }} {{ clubCurrency }}

Calendar Colors

Define keyword-based colors for bookings in the calendar. When a booking's comments contain a keyword, it will be displayed in the matching color.

Loading...

{{ colorForm.id ? 'Edit Color' : 'Add Color' }}

Matched against booking comments (case-insensitive)
Optionally restrict to a specific booking type
{{ colorSuccess }}
{{ colorError }}
Color Keyword Booking Type Actions
{{ color.hex }}
{{ color.keyword }} {{ matchTypeName(color.matchType) }}
No calendar colors configured yet. Add one above.

Send Push Notification

Send a push notification to players at this club.

Filter Recipients

{{ p.firstName }} {{ p.lastName }} Lvl {{ playerLevel(p.points) }}
{{ notifSelectedPlayer.firstName }} {{ notifSelectedPlayer.lastName }} ×

Notification Content

{{ notifSuccess }}
{{ notifError }}

Club Admins

Manage who can access this club's backoffice and mobile-app admin features. Admins must already have a Courtio app account (phone-based).

Add Admin

{{ adminFormSuccess }}
{{ adminFormError }}

Loading...

No admins for this club.

Name Phone Role
{{ ((a.firstName || '') + ' ' + (a.lastName || '')).trim() || '—' }} {{ a.phone }} {{ a.role }} (you)

Playtomic Sync

Configure two-way sync with Playtomic for this club.

Loading...

Sync: Courtio → Playtomic (playtomic user and password)

Credentials used to create blocking events on Playtomic when bookings are made in Courtio. Use a Playtomic account with minimal rights (e.g. receptionist) — it only needs to create and delete bookings.

Found in your Playtomic Manager URL: manager.playtomic.io/tenant-id/scheduler

Sync: Playtomic → Courtio (gmail email and app-password)

Gmail inbox that receives Playtomic booking notifications. Used to sync Playtomic bookings into Courtio.

Use a Gmail App Password, not your regular password.
{{ playtomicSuccess }}
{{ playtomicError }}

Viva.com Payment Credentials

Leave blank if the club is not yet onboarded at viva.com.

Loading...

{{ paymentSettingsSuccess }}
{{ paymentSettingsError }}

VIP Memberships

Players with a VIP membership pay nothing for matches in this club. Default = every match free. Morning first = one free match per day, starting at or before 15:00 and ending by 16:30.

Add {{ vipTypeTab === 'morning_first' ? 'morning_first' : 'default' }} VIP

{{ p.firstName }} {{ p.lastName }} — {{ p.phone || 'no phone' }}
Selected: {{ vipSelectedPlayer.firstName }} {{ vipSelectedPlayer.lastName }} (id {{ vipSelectedPlayer.id }})
{{ vipError }}

{{ vipTypeTab === 'morning_first' ? 'Morning-first' : 'Default' }} members

Loading…

No members in this category.

Player Phone Expires
{{ m.firstName }} {{ m.lastName }} {{ m.phone || '—' }} {{ m.expiresAt || 'never' }}

Test Login

Logging in with phone +40777999000 and code 123456 will sign in as the player below. Leave unset to fall back to the default test user.

Loading...

Currently mapped to: {{ (testLogin.player.firstName || '') + ' ' + (testLogin.player.lastName || '') }} — {{ testLogin.player.phone || 'no phone' }} (userId {{ testLogin.userId }}) Not set — falling back to default test user.
{{ testLoginSuccess }}
{{ testLoginError }}