Courtio - {{ selectedClubName }} Dashboard

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 }}

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() : '—') }} Playtomic Refund Paid Manual 💵 Manual 💳 VIP 👑 Manual {{ p.markerFirstName ? p.markerFirstName + ' ' + p.markerLastName : '—' }} {{ formatDate(p.paidAt) }}

Balance

Stripe balance and payout status for your club.

Loading...

No Stripe account connected.

Available
{{ (b.amount / 100).toFixed(2) }} {{ b.currency.toUpperCase() }}
0.00
Pending
{{ (b.amount / 100).toFixed(2) }} {{ b.currency.toUpperCase() }}
0.00
Payouts: {{ stripeBalance.payoutSchedule.interval }}, {{ stripeBalance.payoutSchedule.delayDays }}-day delay
In Transit to Bank
{{ (p.amount / 100).toFixed(2) }} {{ p.currency.toUpperCase() }}
0.00

Pending Payouts

Amount Expected Arrival Status
{{ (p.amount / 100).toFixed(2) }} {{ p.currency.toUpperCase() }} {{ new Date(p.arrival_date * 1000).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }) }} {{ p.status }}

In Transit

Amount Expected Arrival Status
{{ (p.amount / 100).toFixed(2) }} {{ p.currency.toUpperCase() }} {{ new Date(p.arrival_date * 1000).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }) }} {{ p.status }}

Payout History

No completed payouts yet.
Amount Arrival Date Created
{{ (p.amount / 100).toFixed(2) }} {{ p.currency.toUpperCase() }} {{ new Date(p.arrival_date * 1000).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }) }} {{ new Date(p.created * 1000).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }) }}

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') }} Phone Level Points {{ sortArrow('points') }} Type Matches {{ sortArrow('matchCount') }} Last Active {{ sortArrow('lastPlayed') }}
{{ (p.firstName?.[0] || '') + (p.lastName?.[0] || '') }}
{{ p.firstName }} {{ p.lastName }}
{{ p.gender === 0 ? 'Male' : 'Female' }}
{{ p.phone || '—' }} {{ Math.floor(p.points / 100) + 1 }} {{ p.points }} {{ playerTypeName(p.type) }} {{ p.matchCount }} {{ 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.

Stripe Connect

Connect your club to Stripe to accept online payments.

Loading...

💳

No Stripe account connected

Connect a Stripe account to start accepting online payments for bookings.

Account Status

Account ID {{ stripeStatus.stripeAccountId }}
Account Type {{ stripeStatus.accountType }}
Charges Enabled {{ stripeStatus.chargesEnabled ? 'Yes' : 'No' }}
Payouts Enabled {{ stripeStatus.payoutsEnabled ? 'Yes' : 'No' }}
Details Submitted {{ stripeStatus.detailsSubmitted ? 'Yes' : 'No' }}
Pending Requirements {{ stripeStatus.requirements.currently_due.length }} remaining
{{ stripeError }}

Send Push Notification

Send a push notification to players at this club.

Filter Recipients

{{ p.firstName }} {{ p.lastName }} Lvl {{ Math.floor(p.points / 100) }}
{{ notifSelectedPlayer.firstName }} {{ notifSelectedPlayer.lastName }} ×

Notification Content

{{ notifSuccess }}
{{ notifError }}

Backoffice Users

Manage who has access to this club's backoffice.

Invite User

{{ inviteSuccess }}
{{ inviteError }}

Loading...

No users found.

Name Email Role
{{ u.name }} {{ u.email }} {{ u.role }} (you)

Mobile App Admins

Manage which mobile app users have admin privileges for this club.

Add App Admin

{{ appAdminSuccess }}
{{ appAdminError }}

Loading...

No app admins for this club.

Name Phone
{{ (a.firstName || '') + ' ' + (a.lastName || '') }} {{ a.phone }}

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 }}