diff --git a/dictionaries/en.json.backup b/dictionaries/en.json.backup new file mode 100644 index 0000000..01af7b5 --- /dev/null +++ b/dictionaries/en.json.backup @@ -0,0 +1,840 @@ +{ + "Menu": "Menu", + "Navigate your game": "Navigate your game", + "Login": "Login", + "Continue with SwissOID": "Continue with SwissOID", + "Authentication Required": "Authentication Required", + "Please sign in to continue": "Please sign in to continue", + "You'll be redirected to SwissOID to sign in securely": "You'll be redirected to SwissOID to sign in securely", + "Secure OAuth 2.0 / OpenID Connect via SwissOID": "Secure OAuth 2.0 / OpenID Connect via SwissOID", + "Secure OAuth 2.0 / OpenID Connect": "Secure OAuth 2.0 / OpenID Connect", + "Secure OAuth 2.0 / OpenID Connect • Join thousands of players": "Secure OAuth 2.0 / OpenID Connect • Join thousands of players", + "We don't see or store your password": "We don't see or store your password", + "By continuing, you agree to our": "By continuing, you agree to our", + "Terms": "Terms", + "and": "and", + "Privacy Policy": "Privacy Policy", + "Register": "Register", + "Dashboard": "Dashboard", + "Booking": "Booking", + "Settings": "Settings", + "Find Partners": "Find Partners", + "Player Lookup": "Player Lookup", + "Language": "Language", + "Search for players": "Search for players", + "Click name to view profile": "Click name to view profile", + "Click to view profile": "Click to view profile", + "Loading profile...": "Loading profile...", + "View Full Profile": "View Full Profile", + "Profile data not available": "Profile data not available", + "No recent matches": "No recent matches", + "Recent Form": "Recent Form", + "WhatsApp Share": "WhatsApp Share", + "Logout": "Logout", + "Powered by passion": "Powered by passion", + "© 2024 Playchoo. Because booking is just the start.": "© 2024 Playchoo. Because booking is just the start.", + "Made with ❤️ for players": "Made with ❤️ for players", + "Welcome to {brand}": "Welcome to {brand}", + "Because booking is just the start": "Because booking is just the start", + "The gorgeous booking system that makes players' lives sweet. Find partners instantly, share matches with a simple WhatsApp message, choose your team and position, and track your progress like never before.": "The gorgeous booking system that makes players' lives sweet. Find partners instantly, share matches with a simple WhatsApp message, choose your team and position, and track your progress like never before.", + "WhatsApp Integration": "WhatsApp Integration", + "Smart Partner Matching": "Smart Partner Matching", + "Level Tracking": "Level Tracking", + "Login with SwissOID": "Login with SwissOID", + "Create Account": "Create Account", + "Secure authentication powered by SwissOID • Join thousands of players": "Secure authentication powered by SwissOID • Join thousands of players", + "Secure authentication powered by SwissOID • Streamline your club management": "Secure authentication powered by SwissOID • Streamline your club management", + "Go to Dashboard": "Go to Dashboard", + "Welcome back! Ready to find your next match?": "Welcome back! Ready to find your next match?", + "Why Players Choose {brand}": "Why Players Choose {brand}", + "Every feature designed to make your game better, your connections stronger, and your experience unforgettable": "Every feature designed to make your game better, your connections stronger, and your experience unforgettable", + "Secure & Trusted": "Secure & Trusted", + "Protected by Swiss ID authentication. Your data is safe, your matches are verified, your peace of mind is guaranteed.": "Protected by Swiss ID authentication. Your data is safe, your matches are verified, your peace of mind is guaranteed.", + "WhatsApp Magic": "WhatsApp Magic", + "Share matches instantly with a simple, beautiful message. No apps to download, no complicated links - just pure simplicity.": "Share matches instantly with a simple, beautiful message. No apps to download, no complicated links - just pure simplicity.", + "Smart Matching": "Smart Matching", + "Find partners who match your skill level, schedule, and playing style. Quality connections, every time.": "Find partners who match your skill level, schedule, and playing style. Quality connections, every time.", + "Effortless Booking": "Effortless Booking", + "Book courts, organize teams, manage positions - all in one beautiful interface that just works.": "Book courts, organize teams, manage positions - all in one beautiful interface that just works.", + "Watch your skills grow with intelligent tracking. See your progress, celebrate improvements, reach new heights.": "Watch your skills grow with intelligent tracking. See your progress, celebrate improvements, reach new heights.", + "Made with Love": "Made with Love", + "Built by players, for players. Every pixel crafted with passion, every feature born from real needs.": "Built by players, for players. Every pixel crafted with passion, every feature born from real needs.", + "Happy Players": "Happy Players", + "Matches Organized": "Matches Organized", + "Player Rating": "Player Rating", + "Skill Assessment": "Skill Assessment", + "Answer questions to determine your skill level": "Answer questions to determine your skill level", + "Assessment not found or has been removed": "Assessment not found or has been removed", + "This assessment is private and cannot be viewed": "This assessment is private and cannot be viewed", + "Failed to load assessment result": "Failed to load assessment result", + "An error occurred while loading the assessment": "An error occurred while loading the assessment", + "My Badminton Assessment Result": "My Badminton Assessment Result", + "Check out my badminton skill assessment - Level {{level}}!": "Check out my badminton skill assessment - Level {{level}}!", + "Unable to Load Assessment": "Unable to Load Assessment", + "Take Your Own Assessment": "Take Your Own Assessment", + "No assessment data available": "No assessment data available", + "Assessment by": "Assessment by", + "Completed on": "Completed on", + "Want to test your own skills?": "Want to test your own skills?", + "Take the assessment and see how you compare!": "Take the assessment and see how you compare!", + "Start Your Assessment": "Start Your Assessment", + "Share Your Results": "Share Your Results", + "This assessment is locked and can be shared": "This assessment is locked and can be shared", + "Anonymous": "Anonymous", + "Share on WhatsApp": "Share on WhatsApp", + "Check out my badminton skill assessment": "Check out my badminton skill assessment", + "Unlock": "Unlock", + "Select Country Mode": "Select Country Mode", + "Skill Rating": "Skill Rating", + "What's my level?": "What's my level?", + "Start Assessment": "Start Assessment", + "Previous": "Previous", + "Next": "Next", + "Yes": "Yes", + "No": "No", + "Swipe or Tap": "Swipe or Tap", + "Submit": "Submit", + "Submitting...": "Submitting...", + "Saving...": "Saving...", + "Starting...": "Starting...", + "Loading": "Loading", + "Loading assessment...": "Loading assessment...", + "Question": "Question", + "Level": "Level", + "Points": "Points", + "Confidence": "Confidence", + "Answered": "Answered", + "Select your answer below": "Select your answer below", + "Assessment Complete!": "Assessment Complete!", + "Your Level": "Your Level", + "Total Points Earned": "Total Points Earned", + "Assessment Confidence": "Assessment Confidence", + "Performance Breakdown": "Performance Breakdown", + "Save": "Save", + "Save as My Skill Level": "Save as My Skill Level", + "Save your assessment result?": "Save your assessment result?", + "Your skill level will be updated to Level {{level}} on your profile": "Your skill level will be updated to Level {{level}} on your profile", + "Not now": "Not now", + "Retake Assessment": "Retake Assessment", + "Saved Successfully": "Saved Successfully", + "Assessment Progress": "Assessment Progress", + "By Category": "By Category", + "Quick Navigation": "Quick Navigation", + "Technical": "Technical", + "Tactical": "Tactical", + "Competition": "Competition", + "Technical Skills": "Technical Skills", + "Tactical Knowledge": "Tactical Knowledge", + "Competition Experience": "Competition Experience", + "Beginner": "Beginner", + "Novice": "Novice", + "Intermediate": "Intermediate", + "Competent": "Competent", + "Proficient": "Proficient", + "Advanced": "Advanced", + "Expert": "Expert", + "Elite": "Elite", + "Master": "Master", + "Never": "Never", + "Rarely": "Rarely", + "Sometimes": "Sometimes", + "Often": "Often", + "Always": "Always", + "Frequently": "Frequently", + "Technical and tactical questions only": "Technical and tactical questions only", + "Includes competition questions": "Includes competition questions", + "You have an assessment in progress": "You have an assessment in progress", + "Progress": "Progress", + "Switzerland": "Switzerland", + "France": "France", + "Ready to Transform Your Game?": "Ready to Transform Your Game?", + "Start Playing Today": "Start Playing Today", + "Username": "Username", + "Book Your Next Match": "Book Your Next Match", + "Password": "Password", + "Update Club Account": "Update Club Account", + "Connect Club Account": "Connect Club Account", + "Failed to save credentials": "Failed to save credentials", + "These credentials have already been claimed. You should only claim your own credentials. This is important to get an accurate level measurement.": "These credentials have already been claimed. You should only claim your own credentials. This is important to get an accurate level measurement.", + "Network error occurred": "Network error occurred", + "Refreshing...": "Refreshing...", + "Refreshing session...": "Refreshing session...", + "Cancel": "Cancel", + "Maybe later": "Maybe later", + "Confirm": "Confirm", + "Confirm Change": "Confirm Change", + "Try again": "Try again", + "Confirm Booking": "Confirm Booking", + "Who do you want to play with?": "Who do you want to play with?", + "Click below to start adding partners.": "Click below to start adding partners.", + "Add Partner": "Add Partner", + "Ready to confirm?": "Ready to confirm?", + "Click below to finalize your reservation.": "Click below to finalize your reservation.", + "Booking...": "Booking...", + "Almost done!": "Almost done!", + "Proceed to payment to complete your booking.": "Proceed to payment to complete your booking.", + "Go to Payment": "Go to Payment", + "In progress": "In progress", + "Players joined": "Players joined", + "No players yet": "No players yet", + "Ends in {time}": "Ends in {time}", + "Book": "Book", + "View": "View", + "Join request sent": "Join request sent", + "Failed to send request": "Failed to send request", + "Network error": "Network error", + "Request to join booking": "Request to join booking", + "Request to join this booking?": "Request to join this booking?", + "Available Courts": "Available Courts", + "Select a date to view available time slots": "Select a date to view available time slots", + "Live updates • Past slots hidden automatically": "Live updates • Past slots hidden automatically", + "Date:": "Date:", + "Timeline": "Timeline", + "Courts": "Courts", + "No courts available": "No courts available", + "Try selecting a different date or check back later.": "Try selecting a different date or check back later.", + "No slots available": "No slots available", + "Try selecting a different filter.": "Try selecting a different filter.", + "Report Score": "Report Score", + "Won": "Won", + "Lost": "Lost", + "Hide detailed score": "Hide detailed score", + "Add detailed score": "Add detailed score", + "Add set": "Add set", + "Success": "Success", + "Provide your club login so we can connect your account": "Provide your club login so we can connect your account", + "Loading...": "Loading...", + "Error Loading Dashboard": "Error Loading Dashboard", + "Your Dashboard": "Your Dashboard", + "Track your game, celebrate victories, and never miss a match": "Track your game, celebrate victories, and never miss a match", + "Matches Won": "Matches Won", + "Upcoming Games": "Upcoming Games", + "Win Streak": "Win Streak", + "Upcoming Matches": "Upcoming Matches", + "Get ready for your next games": "Get ready for your next games", + "Pending Scores": "Pending Scores", + "Report your match results": "Report your match results", + "Score Reporting": "Score Reporting", + "Track your past performances": "Track your past performances", + "Achievement Unlocked!": "Achievement Unlocked!", + "Legendary Champion": "Legendary Champion", + "Unstoppable Force": "Unstoppable Force", + "Win Streak Master": "Win Streak Master", + "Rising Star": "Rising Star", + "You've won {count} matches in a row.": "You've won {count} matches in a row.", + "You are absolutely unstoppable!": "You are absolutely unstoppable!", + "Your dominance is legendary!": "Your dominance is legendary!", + "Keep the momentum going!": "Keep the momentum going!", + "Great start to your winning streak!": "Great start to your winning streak!", + "Account Search": "Account Search", + "Find and manage accounts": "Find and manage accounts", + "Accounts": "Accounts", + "Sign out": "Sign out", + "Signing out...": "Signing out...", + "Search Accounts": "Search Accounts", + "Enter a name or account number to find accounts": "Enter a name or account number to find accounts", + "Search by name or account number...": "Search by name or account number...", + "Search": "Search", + "Searching...": "Searching...", + "Searching accounts...": "Searching accounts...", + "Found {count} accounts": "Found {count} accounts", + "Search completed": "Search completed", + "No accounts found matching your search.": "No accounts found matching your search.", + "Search failed. Please try again.": "Search failed. Please try again.", + "Network error. Please check your connection.": "Network error. Please check your connection.", + "No Results Found": "No Results Found", + "Try adjusting your search terms or check the spelling.": "Try adjusting your search terms or check the spelling.", + "Search Results": "Search Results", + "{count} accounts found": "{count} accounts found", + "Account ID": "Account ID", + "Welcome to Account Search": "Welcome to Account Search", + "Start typing in the search box above to find accounts by name or account number.": "Start typing in the search box above to find accounts by name or account number.", + "Results will appear instantly as you type.": "Results will appear instantly as you type.", + "Real-time search": "Real-time search", + "Instant results": "Instant results", + "Smart matching": "Smart matching", + "Failed to load bookings": "Failed to load bookings", + "Network error while loading bookings": "Network error while loading bookings", + "Today": "Today", + "Tomorrow": "Tomorrow", + "Yesterday": "Yesterday", + "Starting now": "Starting now", + "Next Match": "Next Match", + "Next {count} Matches": "Next {count} Matches", + "Ready to play? Here's what's coming up": "Ready to play? Here's what's coming up", + "Matches": "Matches", + "{count}/4 players": "{count}/4 players", + "View Match": "View Match", + "Want to play more?": "Want to play more?", + "Book Another Match": "Book Another Match", + "Court {court} • {duration} minutes": "Court {court} • {duration} minutes", + "Court {court}": "Court {court}", + "No match history yet": "No match history yet", + "Play some matches to see your history and track your progress!": "Play some matches to see your history and track your progress!", + "Book Your First Match": "Book Your First Match", + "View Details": "View Details", + "Showing recent matches": "Showing recent matches", + "View Full History": "View Full History", + "Confirmed": "Confirmed", + "Trusted": "Trusted", + "Waiting": "Waiting", + "Loading pending scores...": "Loading pending scores...", + "All": "All", + "All caught up!": "All caught up!", + "No pending scores to report right now.": "No pending scores to report right now.", + "Failed to submit": "Failed to submit", + "Failed": "Failed", + "Search and add players to your game": "Search and add players to your game", + "Searching players...": "Searching players...", + "Start typing to search": "Start typing to search", + "Enter at least 2 characters to find partners": "Enter at least 2 characters to find partners", + "No players found": "No players found", + "Try a different search term": "Try a different search term", + "Click to add to your game": "Click to add to your game", + "Find the perfect partners for your game": "Find the perfect partners for your game", + "No upcoming matches": "No upcoming matches", + "Your calendar is clear! Time to book your next exciting match.": "Your calendar is clear! Time to book your next exciting match.", + "Book a Match": "Book a Match", + "Close": "Close", + "Loading slot details...": "Loading slot details...", + "Failed to load slot": "Failed to load slot", + "Network error while loading slot": "Network error while loading slot", + "Book Your Court": "Book Your Court", + "No slot found": "No slot found", + "Available": "Available", + "Players": "Players", + "Go Back": "Go Back", + "Login Required": "Login Required", + "Please login to continue.": "Please login to continue.", + "Return to Home": "Return to Home", + "Login Failed": "Login Failed", + "No Token Provided": "No Token Provided", + "We couldn't find an authentication token. Please try logging in again.": "We couldn't find an authentication token. Please try logging in again.", + "Logging you in...": "Logging you in...", + "Please wait while we authenticate your session": "Please wait while we authenticate your session", + "Secure Authentication": "Secure Authentication", + "Redirecting to dashboard": "Redirecting to dashboard", + "Return to Login": "Return to Login", + "Need help? Contact support for assistance.": "Need help? Contact support for assistance.", + "Please wait": "Please wait", + "Secured by Playchoo Authentication System": "Secured by Playchoo Authentication System", + "Encrypted": "Encrypted", + "Secure": "Secure", + "Protected": "Protected", + "Signing you out...": "Signing you out...", + "Securing your session": "Securing your session", + "Successfully signed out!": "Successfully signed out!", + "Your session has been securely ended": "Your session has been securely ended", + "Redirecting...": "Redirecting...", + "Taking you back to the homepage": "Taking you back to the homepage", + "Thanks for using Playchoo": "Thanks for using Playchoo", + "See you on the court! 🎾": "See you on the court! 🎾", + "Click to select": "Click to select", + "No clubs available": "No clubs available", + "Please contact support if you believe this is an error.": "Please contact support if you believe this is an error.", + "No sports available": "No sports available", + "This club doesn't have any sports configured yet.": "This club doesn't have any sports configured yet.", + "Loading clubs...": "Loading clubs...", + "Choose Your Sport": "Choose Your Sport", + "Select Your Club": "Select Your Club", + "What sport do you play at {club}?": "What sport do you play at {club}?", + "Choose the club where you play": "Choose the club where you play", + "Failed to load clubs": "Failed to load clubs", + "Failed to save preferences": "Failed to save preferences", + "Select to continue": "Select to continue", + "Back to Clubs": "Back to Clubs", + "Select Club": "Select Club", + "Default Club & Sport": "Default Club & Sport", + "Your preferred club and sport for seamless bookings": "Your preferred club and sport for seamless bookings", + "Edit": "Edit", + "Club Connection": "Club Connection", + "Your connection status with the club management system": "Your connection status with the club management system", + "Connection Status": "Connection Status", + "Not claimed": "Not claimed", + "Contact your club to link your account for seamless booking": "Contact your club to link your account for seamless booking", + "Other Linked Accounts": "Other Linked Accounts", + "Choose your preferred club and sport": "Choose your preferred club and sport", + "Update Default Club & Sport": "Update Default Club & Sport", + "Customize your experience and manage your account preferences with ease": "Customize your experience and manage your account preferences with ease", + "Reservation created! Proceed to payment.": "Reservation created! Proceed to payment.", + "Booking confirmed!": "Booking confirmed!", + "Failed to book slot": "Failed to book slot", + "Booking failed": "Booking failed", + "Processing your booking...": "Processing your booking...", + "Reconnecting to booking service...": "Reconnecting to booking service...", + "Booking Details": "Booking Details", + "This slot is already booked": "This slot is already booked", + "Redirecting you to view the booking details...": "Redirecting you to view the booking details...", + "Failed to load booking": "Failed to load booking", + "Network error while loading booking": "Network error while loading booking", + "Invalid booking data received from server": "Invalid booking data received from server", + "Invalid booking date format": "Invalid booking date format", + "No booking found": "No booking found", + "Pending Position Requests": "Pending Position Requests", + "Players requesting to swap positions with you": "Players requesting to swap positions with you", + "Cancelling...": "Cancelling...", + "Approving...": "Approving...", + "Rejecting...": "Rejecting...", + "Approve": "Approve", + "Reject": "Reject", + "Request cancelled": "Request cancelled", + "Failed to cancel request": "Failed to cancel request", + "Request rejected": "Request rejected", + "Failed to reject request": "Failed to reject request", + "Request approved and positions swapped!": "Request approved and positions swapped!", + "Failed to approve request": "Failed to approve request", + "Pending Join Requests": "Pending Join Requests", + "Players requesting to join your booking": "Players requesting to join your booking", + "Waiting for approval": "Waiting for approval", + "Seat requested": "Seat requested", + "You already asked for that seat.": "You already asked for that seat.", + "Slot full": "Slot full", + "Position taken": "Position taken", + "Request expired": "Request expired", + "Accepted – slot updated.": "Accepted – slot updated.", + "Red Team": "Red Team", + "Blue Team": "Blue Team", + "You": "You", + "Sport": "Sport", + "Club information not available": "Club information not available", + "Failed to change position": "Failed to change position", + "Side": "Side", + "Left": "Left", + "Right": "Right", + "Full": "Full", + "Booked": "Booked", + "Drag your avatar to change positions. Other players will need to approve swaps.": "Drag your avatar to change positions. Other players will need to approve swaps.", + "and": "and", + "to {request}": "to {request}", + "move to the {side} side": "move to the {side} side", + "switch to the {team} team": "switch to the {team} team", + "move you to the {side} side": "move you to the {side} side", + "switch you to the {team} team": "switch you to the {team} team", + "{requesterName} wants{requestLabel} with you": "{requesterName} wants{requestLabel} with you", + "{requesterName} wants{requestLabel} with {approverName}": "{requesterName} wants{requestLabel} with {approverName}", + "You would {effect}": "You would {effect}", + "This would {effect}": "This would {effect}", + "{requesterName} would {effect}": "{requesterName} would {effect}", + "Match closed header": "🎾 Match closed 🎾", + "Match open header": "🎾 Match open 🎾", + "Urgent": "URGENT", + "{duration} min": "{duration} min", + "{count} courts • {available} available": "{count} courts • {available} available", + "{count} slots": "{count} slots", + "{count} available": "{count} available", + "Failed to load slots": "Failed to load slots", + "Network error while loading slots": "Network error while loading slots", + "Error": "Error", + "Visible Slots": "Visible Slots", + "Total Slots": "Total Slots", + "Pending": "Pending", + "{count} past slots hidden automatically": "{count} past slots hidden automatically", + "Authenticating": "Authenticating", + "Authentication Failed": "Authentication Failed", + "Authentication successful. Redirecting to your dashboard...": "Authentication successful. Redirecting to your dashboard...", + "Invalid Token": "Invalid Token", + "The authentication token is missing or invalid.": "The authentication token is missing or invalid.", + "Verifying your access token...": "Verifying your access token...", + "Login failed": "Login failed", + "No players assigned": "No players assigned", + "Welcome Back!": "Welcome Back!", + "Welcome!": "Welcome!", + "Club": "Club", + "Select Account": "Select Account", + "vs": "vs", + "Disputed": "Disputed", + "Needs Review": "Needs Review", + "Review": "Review", + "Resolve Dispute": "Resolve Dispute", + "Accept": "Accept", + "Detailed Score": "Detailed Score", + "Dispute Resolution": "Dispute Resolution", + "Match Score": "Match Score", + "Match Results - Dispute Resolution": "Match Results - Dispute Resolution", + "Match Results": "Match Results", + "Confirm Score": "Confirm Score", + "Accept Score": "Accept Score", + "Reported by": "Reported by", + "Accept This Score": "Accept This Score", + "No sets were played": "No sets were played", + "You dominated from start to finish": "You dominated from start to finish", + "The start was rough but you managed to overtake at the end": "The start was rough but you managed to overtake at the end", + "You got ahead early and held your nerve to seal the victory": "You got ahead early and held your nerve to seal the victory", + "They dominated from start to finish": "They dominated from start to finish", + "Great start, but things slipped away in the end": "Great start, but things slipped away in the end", + "It was a tight battle, but they pulled through when it mattered": "It was a tight battle, but they pulled through when it mattered", + "All Matches": "All Matches", + "Needs Score": "Needs Score", + "Completed": "Completed", + "No matches pending score submission": "No matches pending score submission", + "No completed matches": "No completed matches", + "No matches found": "No matches found", + "Set {number}": "Set {number}", + "Report Match Score": "Report Match Score", + "Tell us how the match went": "Tell us how the match went", + "Your Team": "Your Team", + "(You)": "(You)", + "Opponents": "Opponents", + "Match Result": "Match Result", + "Quick Report": "Quick Report", + "Detailed Report": "Detailed Report", + "or": "or", + "We Won!": "We Won!", + "We Lost": "We Lost", + "Hide set scores": "Hide set scores", + "Add set scores": "Add set scores", + "Us": "Us", + "Them": "Them", + "Add another set": "Add another set", + "Please add at least 2 sets for detailed score": "Please add at least 2 sets for detailed score", + "Submit Report": "Submit Report", + "(RED)": "(RED)", + "(BLUE)": "(BLUE)", + "RED TEAM (You)": "RED TEAM (You)", + "RED": "Red", + "BLUE": "Blue", + "Sets show loss": "Sets show loss", + "Sets show win": "Sets show win", + "Force swap": "Force swap", + "Use if you know the other person approves": "Use if you know the other person approves", + "Failed to submit score": "Failed to submit score", + "available": "available", + "pending": "pending", + "booked": "booked", + "coach": "coach", + "club": "club", + "Share on WhatsApp": "Share on WhatsApp", + "{duration}m": "{duration}m", + "{min}m left": "{min}m left", + "Compact": "Compact", + "Player Profile": "Player Profile", + "Player Information": "Player Information", + "Sport Information": "Sport Information", + "Reliability": "Reliability", + "Match Statistics": "Match Statistics", + "Recent Matches": "Recent Matches", + "Member Since": "Member Since", + "Skill Level": "Skill Level", + "Total Gradings": "Total Gradings", + "Reliability Score": "Reliability Score", + "Reporting Rate": "Reporting Rate", + "Consensus Rate": "Consensus Rate", + "Matches Played": "Matches Played", + "Matches Reported": "Matches Reported", + "In Consensus": "In Consensus", + "Score Not Reported": "Score Not Reported", + "Please report the match score": "Please report the match score", + "Player Score Reports": "Player Score Reports", + "Unknown Player": "Unknown Player", + "Reported": "Reported", + "Multiple score reports detected. The match result will be confirmed once all players agree.": "Multiple score reports detected. The match result will be confirmed once all players agree.", + "Total Matches": "Total Matches", + "Wins": "Wins", + "Losses": "Losses", + "Win Rate": "Win Rate", + "Longest Win Streak": "Longest Win Streak", + "matches in last 30 days": "matches in last 30 days", + "matches in last 90 days": "matches in last 90 days", + "Favorite Venue": "Favorite Venue", + "No data available": "No data available", + "Failed to load profile": "Failed to load profile", + "Slot information not loaded yet": "Slot information not loaded yet", + "Inactive": "Inactive", + "Self-Assessment": "Self-Assessment", + "Player's self-reported skill level (1-7)": "Player's self-reported skill level (1-7)", + "Competitive Rating": "Competitive Rating", + "Glicko-2 rating based on match results": "Glicko-2 rating based on match results", + "Rating": "Rating", + "Ranked Matches": "Ranked Matches", + "Competitive games": "Competitive games", + "Rating Confidence": "Rating Confidence", + "High": "High", + "Medium": "Medium", + "Low": "Low", + "No rating data available yet": "No rating data available yet", + "Play ranked matches to build your rating": "Play ranked matches to build your rating", + "Loss Streak": "Loss Streak", + "Elite Winner": "Elite Winner", + "Streak Master": "Streak Master", + "Centurion": "Centurion", + "Experienced": "Experienced", + "Create Your Profile": "Create Your Profile", + "Challenge Player": "Challenge Player", + "Frequent Players": "Frequent Players", + "No playing history yet": "No playing history yet", + "Play more matches to build your network": "Play more matches to build your network", + "Excellent": "Excellent", + "Good": "Good", + "Fair": "Fair", + "Needs Improvement": "Needs Improvement", + "Various venues": "Various venues", + "Last 30 days": "Last 30 days", + "Last 90 days": "Last 90 days", + "/week avg": "/week avg", + "Home Court": "Home Court", + "On-time arrival": "On-time arrival", + "Total bookings": "Total bookings", + "No-shows": "No-shows", + "Unique Players": "Unique Players", + "Most Played With": "Most Played With", + "Best Streak": "Best Streak", + "consecutive wins": "consecutive wins", + "Current Streak": "Current Streak", + "wins in a row": "wins in a row", + "losses in a row": "losses in a row", + "no active streak": "no active streak", + "matches": "matches", + "match": "match", + "W": "W", + "L": "L", + "Trusted Player": "Trusted Player", + "Avg response": "Avg response", + "Last {count} matches": "Last {count} matches", + "No recent matches to display": "No recent matches to display", + "View all {count} matches →": "View all {count} matches →", + "Join thousands of players who've already discovered the joy of effortless booking and perfect matches.": "Join thousands of players who've already discovered the joy of effortless booking and perfect matches.", + "Profile": "Profile", + "Ready to play? Here's what's coming up.": "Ready to play? Here's what's coming up.", + "This club doesn't support this sport": "This club doesn't support this sport", + "We couldn't find that booking": "We couldn't find that booking", + "Your request{requestLabel} is awaiting {approverName}'s approval": "Your request{requestLabel} is awaiting {approverName}'s approval", + "position": "position", + "Join Match": "Join Match", + "Do you want to request to join this match?": "Do you want to request to join this match?", + "Court": "Court", + "Time": "Time", + "Team": "Team", + "Position": "Position", + "Red": "Red", + "Blue": "Blue", + "Match Tiebreak": "Match Tiebreak", + "Match TB": "Match TB", + "Tiebreak Points": "Tiebreak Points", + "Tiebreak (7-6 or 6-7)": "Tiebreak (7-6 or 6-7)", + "Add Set": "Add Set", + "Active": "Active", + "Assessment Locked": "Assessment Locked", + "Back to Home": "Back to Home", + "Booker": "Booker", + "Check out my padel skill assessment results!": "Check out my padel skill assessment results!", + "Collapse": "Collapse", + "Continue Assessment": "Continue Assessment", + "Copied!": "Copied!", + "Copy": "Copy", + "Done": "Done", + "Easy Scheduling": "Easy Scheduling", + "My Padel Assessment Results": "My Padel Assessment Results", + "No level data": "No level data", + "No match history available": "No match history available", + "Share": "Share", + "Share Link": "Share Link", + "Share your results": "Share your results", + "View Profile": "View Profile", + "View Results": "View Results", + "Your assessment is now locked and can be shared. The results cannot be modified.": "Your assessment is now locked and can be shared. The results cannot be modified.", + "Review Answers": "Review Answers", + "Session Locked": "Session Locked", + "This assessment is locked and read-only": "This assessment is locked and read-only", + "Unlock to Edit": "Unlock to Edit", + "Unlocking...": "Unlocking...", + "Play With the Right People.": "Play With the Right People.", + "Every Time.": "Every Time.", + "No more wrong-level matches. Book smarter, play more, and see your progress at a glance.": "No more wrong-level matches. Book smarter, play more, and see your progress at a glance.", + "Always matched at your level": "Always matched at your level", + "Book in seconds": "Book in seconds", + "Track your progress": "Track your progress", + "One-tap invites": "One-tap invites", + "See How It Works": "Sign In to See More", + "Find Your Perfect Match": "Sign Up Now", + "The wrong match kills the fun.": "The wrong match kills the fun.", + "Playing above your level": "Playing above your level", + "= frustration": "= frustration", + "Playing below your level": "Playing below your level", + "= boredom": "= boredom", + "Organizing games": "Organizing games", + "= endless chat chaos": "= endless chat chaos", + "Playchoo fixes this:": "Playchoo fixes this:", + "Always matched with players at your level": "Always matched with players at your level", + "Book in seconds with live availability": "Book in seconds with live availability", + "Track your progress at a glance": "Track your progress at a glance", + "Everything You Need to Play Better": "Everything You Need to Play Better", + "Smart features that work together to transform your game": "Smart features that work together to transform your game", + "Perfect Matchmaking": "Perfect Matchmaking", + "Smart level system: start with your own estimate, then Playchoo adjusts automatically as you play.": "Smart level system: start with your own estimate, then Playchoo adjusts automatically as you play.", + "Always fair, always fun": "Always fair, always fun", + "Save time with partner suggestions": "Save time with partner suggestions", + "See real-time court availability and book instantly.": "See real-time court availability and book instantly.", + "Drag-and-drop players onto the court": "Drag-and-drop players onto the court", + "Timeline and calendar views": "Timeline and calendar views", + "Works for padel, tennis, and more": "Works for padel, tennis, and more", + "Progress That Motivates": "Progress That Motivates", + "See your progress at a glance with stats, streaks, and head-to-heads.": "See your progress at a glance with stats, streaks, and head-to-heads.", + "Earn achievements as you play": "Earn achievements as you play", + "Personal player card brings your game to life": "Personal player card brings your game to life", + "Easy Sharing": "Easy Sharing", + "One-tap WhatsApp invites with all details included.": "One-tap WhatsApp invites with all details included.", + "No app required for your friends": "No app required for your friends", + "Beautiful formatted messages": "Beautiful formatted messages", + "Real-Time Updates": "Real-Time Updates", + "Live court availability, instant confirmations, and automatic conflict detection. Everything updates in real-time.": "Live court availability, instant confirmations, and automatic conflict detection. Everything updates in real-time.", + "Club Ready": "Club Ready", + "Multi-club support, timezone handling, and professional management tools. Perfect for players and clubs alike.": "Multi-club support, timezone handling, and professional management tools. Perfect for players and clubs alike.", + "Simplify Club Management": "Simplify Club Management", + "Professional tools that save hours every week": "Professional tools that save hours every week", + "Multi-Club Support": "Multi-Club Support", + "Manage multiple clubs and locations from one account": "Manage multiple clubs and locations from one account", + "Automatic Scheduling": "Automatic Scheduling", + "Smart timezone handling and conflict detection": "Smart timezone handling and conflict detection", + "Member Management": "Member Management", + "Remote access and credentials for all members": "Remote access and credentials for all members", + "Bring Playchoo to Your Club": "Sign Up Your Club", + "Players and clubs are loving it": "Players and clubs are loving it", + "Finally, I always play at my level — and every match is fun again.": "Finally, I always play at my level — and every match is fun again.", + "The app shows me how I've improved without me even thinking about it.": "The app shows me how I've improved without me even thinking about it.", + "Sarah M., Padel Player": "Sarah M., Padel Player", + "Mike R., Tennis Player": "Mike R., Tennis Player", + "Never play the wrong match again.": "Never play the wrong match again.", + "Book smarter, play at your level, and see your progress at a glance.": "Book smarter, play at your level, and see your progress at a glance.", + "Get Early Access Free": "Sign Up Free", + "Know Your Level": "Know Your Level", + "Curious about your skill level?": "Curious about your skill level?", + "Take the quick test!": "Take the quick test!", + "Get matched with players at your exact level": "Get matched with players at your exact level", + "Share your verified level with your community": "Share your verified level with your community", + "Track your improvement over time": "Track your improvement over time", + "Discover Your Level": "Discover Your Level", + "Takes only 2 minutes": "Takes only 2 minutes", + "Perfect matches guaranteed": "Perfect matches guaranteed", + "Join 1000+ rated players": "Join 1000+ rated players", + "Results saved to your profile • Retake anytime to track progress": "Results saved to your profile • Retake anytime to track progress", + "Theme": "Theme", + "Color Scheme": "Color Scheme", + "Choose your preferred color theme": "Choose your preferred color theme", + "Personalize the appearance of your app": "Personalize the appearance of your app", + "Match Type": "Match Type", + "Ranked": "Ranked", + "Friendly": "Friendly", + "Training": "Training", + "Score required": "Score required", + "Change": "Change", + "Change Match Type": "Change Match Type", + "Current Match Type": "Current Match Type", + "Pending Request": "Pending Request", + "Your Request": "Your Request", + "Change to": "Change to", + "Force Change": "Force Change", + "Pending Requests": "Pending Requests", + "Change To": "Change To", + "Force change without approval": "Force change without approval", + "Skip team approval and apply change immediately": "Skip team approval and apply change immediately", + "Changing...": "Changing...", + "Request Change": "Request Change", + "Match type changed successfully": "Match type changed successfully", + "Match type change request sent": "Match type change request sent", + "Failed to change match type": "Failed to change match type", + "Network error while changing match type": "Network error while changing match type", + "{approved} approved, {pending} pending": "{approved} approved, {pending} pending", + "Approve": "Approve", + "Reject": "Reject", + "Rejected": "Rejected", + "You Approved": "You Approved", + "You Rejected": "You Rejected", + "Cancel Request": "Cancel Request", + "Force Override": "Force Override", + "Force": "Force", + "Request": "Request", + "Forced": "Forced", + "All approvals completed": "All approvals completed", + "Player": "Player", + "Match type request approved": "Match type request approved", + "Failed to approve request": "Failed to approve request", + "Network error while approving request": "Network error while approving request", + "Match type request rejected": "Match type request rejected", + "Failed to reject request": "Failed to reject request", + "Network error while rejecting request": "Network error while rejecting request", + "Unknown Match Type": "Unknown Match Type", + "Cannot change match type for past bookings": "Cannot change match type for past bookings", + "Only players in this booking can change the match type": "Only players in this booking can change the match type", + "Cannot change match type after scores have been submitted": "Cannot change match type after scores have been submitted", + "Match type cannot be changed": "Match type cannot be changed", + "Waiting for approval from": "Waiting for approval from", + "Waiting for approval from these players": "Waiting for approval from these players", + "Approval pending from": "Approval pending from", + "Approval pending from these players": "Approval pending from these players", + "Punctuality Report": "Punctuality Report", + "Punctuality Reports": "Punctuality Reports", + "Reports updated successfully": "Reports updated successfully", + "Reports submitted successfully": "Reports submitted successfully", + "Failed to submit reports": "Failed to submit reports", + "Network error while submitting reports": "Network error while submitting reports", + "You have reached the maximum number of updates for this match": "You have reached the maximum number of updates for this match", + "Update {count}/5": "Update {count}/5", + "You can update your punctuality reports up to 5 times": "You can update your punctuality reports up to 5 times", + "Report how punctual each player was for this match (0 = on time)": "Report how punctual each player was for this match (0 = on time)", + "Consensus: {minutes} min late": "Consensus: {minutes} min late", + "Disputed": "Disputed", + "Pending reports": "Pending reports", + "min": "min", + "Late": "Late", + "Update Reports": "Update Reports", + "Submit Reports": "Submit Reports", + "Submitting...": "Submitting...", + "Anyone late to the match?": "Anyone late to the match?", + "Update punctuality report": "Update punctuality report", + "Update Punctuality Report": "Update Punctuality Report", + "You reported late arrivals": "You reported late arrivals", + "You reported everyone on time": "You reported everyone on time", + "{count} updates remaining": "{count} updates remaining", + "Select any players who were late to the match": "Select any players who were late to the match", + "Set how many minutes late each player was": "Set how many minutes late each player was", + "No players selected - everyone was on time!": "No players selected - everyone was on time!", + "Update Report": "Update Report", + "Submit Report": "Submit Report", + "1 minute late": "1 minute late", + "{minutes} minutes late": "{minutes} minutes late", + "Streak": "Streak", + "Session Expiring": "Session Expiring", + "Your session will expire in {minutes} minutes.": "Your session will expire in {minutes} minutes.", + "Your session will expire in less than a minute.": "Your session will expire in less than a minute.", + "Stay logged in": "Stay logged in", + "Refreshing...": "Refreshing...", + "Pending Position Swaps": "Pending Position Swaps", + "Multi-player position changes requiring approval": "Multi-player position changes requiring approval", + "Your swap request": "Your swap request", + "{initiator} initiated a swap": "{initiator} initiated a swap", + "{pending} of {total} approvals pending": "{pending} of {total} approvals pending", + "Cancel Swap": "Cancel Swap", + "Approved": "Approved", + "Auto-approved": "Auto-approved", + "Position 1 (Blue, Left)": "Position 1 (Blue, Left)", + "Position 2 (Blue, Right)": "Position 2 (Blue, Right)", + "Position 3 (Red, Left)": "Position 3 (Red, Left)", + "Position 4 (Red, Right)": "Position 4 (Red, Right)", + "Your approval is required for this swap to execute": "Your approval is required for this swap to execute", + "Waiting for all players to approve": "Waiting for all players to approve", + "All players must approve before positions change": "All players must approve before positions change", + "Swap approved successfully": "Swap approved successfully", + "Failed to approve swap": "Failed to approve swap", + "Network error while approving swap": "Network error while approving swap", + "Swap cancelled successfully": "Swap cancelled successfully", + "Failed to cancel swap": "Failed to cancel swap", + "Network error while cancelling swap": "Network error while cancelling swap", + "You already have a pending request for this match type. Please wait for approval or cancel your current request.": "You already have a pending request for this match type. Please wait for approval or cancel your current request.", + "Network error while cancelling request": "Network error while cancelling request", + "Request approved": "Request approved", + "Failed to force change": "Failed to force change", + "Network error while forcing change": "Network error while forcing change", + "Error": "Error", + "Dismiss": "Dismiss", + "Your Approval Needed": "Your Approval Needed", + "Position swap requires your approval": "Position swap requires your approval", + "of": "of", + "pending": "pending", + "Your position change": "Your position change", + "Show details": "Show details", + "Hide details": "Hide details", + "swap request": "swap request", + "Waiting for": "Waiting for", + "approval(s)": "approval(s)", + "All approved": "All approved" +} diff --git a/src/app/[locale]/admin/clubs/[club_id]/slot-definitions/SlotDefinitionForm.tsx b/src/app/[locale]/admin/clubs/[club_id]/slot-definitions/SlotDefinitionForm.tsx new file mode 100644 index 0000000..74de7bc --- /dev/null +++ b/src/app/[locale]/admin/clubs/[club_id]/slot-definitions/SlotDefinitionForm.tsx @@ -0,0 +1,376 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { X, AlertCircle, Loader2 } from 'lucide-react'; +import type { SlotDefinition, SlotDefinitionRequest, DayOfWeek, ValidationError } from '@/src/types/slot-definitions'; +import { DAY_NAMES, formatTimeForAPI } from '@/src/types/slot-definitions'; +import { createSlotDefinition, updateSlotDefinition } from '@/src/lib/api/slot-definitions'; + +interface SlotDefinitionFormProps { + clubId: number; + courts: { court_id: number; name: string }[]; + definition?: SlotDefinition; + onClose: () => void; + onSuccess: () => void; +} + +export default function SlotDefinitionForm({ + clubId, + courts, + definition, + onClose, + onSuccess, +}: SlotDefinitionFormProps) { + const isEditing = !!definition; + + // Form state + const [courtId, setCourtId] = useState(definition?.court_id || (courts[0]?.court_id || 0)); + const [dow, setDow] = useState(definition?.dow || 0); + const [startsAt, setStartsAt] = useState(definition ? definition.starts_at.substring(0, 5) : '09:00'); + const [durationMinutes, setDurationMinutes] = useState(definition?.duration_minutes || 90); + const [capacity, setCapacity] = useState(definition?.capacity || 4); + const [validFrom, setValidFrom] = useState(definition?.valid_from || getTodayString()); + const [validTo, setValidTo] = useState(definition?.valid_to || ''); + const [noEndDate, setNoEndDate] = useState(!definition?.valid_to); + const [ruleDescription, setRuleDescription] = useState(definition?.rule?.description || ''); + + // UI state + const [loading, setLoading] = useState(false); + const [errors, setErrors] = useState>({}); + const [generalError, setGeneralError] = useState(''); + + useEffect(() => { + if (noEndDate) { + setValidTo(''); + } + }, [noEndDate]); + + function getTodayString(): string { + const today = new Date(); + return today.toISOString().split('T')[0]; + } + + function validateForm(): boolean { + const newErrors: Record = {}; + + if (!courtId) { + newErrors.court_id = 'Please select a court'; + } + + if (!startsAt) { + newErrors.starts_at = 'Start time is required'; + } + + if (durationMinutes <= 0) { + newErrors.duration_minutes = 'Duration must be greater than 0'; + } + + if (capacity <= 0) { + newErrors.capacity = 'Capacity must be greater than 0'; + } + + if (!validFrom) { + newErrors.valid_from = 'Start date is required'; + } + + if (validTo && validFrom && validTo < validFrom) { + newErrors.valid_to = 'End date must be after start date'; + } + + // Check if end time exceeds 24:00 + const [hours, minutes] = startsAt.split(':').map(Number); + const totalMinutes = hours * 60 + minutes + durationMinutes; + if (totalMinutes >= 24 * 60) { + newErrors.duration_minutes = 'Slot cannot extend past midnight'; + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + } + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + + if (!validateForm()) { + return; + } + + setLoading(true); + setGeneralError(''); + + const request: SlotDefinitionRequest = { + court_id: courtId, + dow, + starts_at: formatTimeForAPI(startsAt), + duration_minutes: durationMinutes, + capacity, + valid_from: validFrom, + valid_to: noEndDate ? undefined : validTo, + rule: { + weekly: true, + description: ruleDescription || undefined, + }, + }; + + const result = isEditing + ? await updateSlotDefinition(clubId, definition.slot_definition_id, request) + : await createSlotDefinition(clubId, request); + + if (result.success) { + onSuccess(); + onClose(); + } else { + // Handle validation errors + if (result.error.code === 'validation_error' && result.error.errors) { + const fieldErrors: Record = {}; + result.error.errors.forEach((err: ValidationError) => { + fieldErrors[err.field] = err.message; + }); + setErrors(fieldErrors); + } else if (result.error.code === 'slot_definition_overlap') { + setGeneralError('A slot definition already exists for this court, day, and time. Please choose a different time or court.'); + } else { + setGeneralError(result.error.detail || 'An error occurred. Please try again.'); + } + } + + setLoading(false); + } + + return ( +
+
+ {/* Header */} +
+

+ {isEditing ? 'Edit Slot Definition' : 'Create Slot Definition'} +

+ +
+ + {/* General Error */} + {generalError && ( +
+ +

{generalError}

+
+ )} + + {/* Form */} +
+ {/* Court Selection */} +
+ + + {errors.court_id && ( +

{errors.court_id}

+ )} +
+ + {/* Day of Week */} +
+ + +
+ + {/* Time and Duration */} +
+
+ + setStartsAt(e.target.value)} + className={`w-full px-4 py-3 border-2 rounded-lg font-medium transition-colors ${ + errors.starts_at + ? 'border-red-300 focus:border-red-500' + : 'border-slate-200 focus:border-slate-900' + } focus:outline-none`} + disabled={loading} + /> + {errors.starts_at && ( +

{errors.starts_at}

+ )} +
+ +
+ + setDurationMinutes(parseInt(e.target.value) || 0)} + min="1" + step="15" + className={`w-full px-4 py-3 border-2 rounded-lg font-medium transition-colors ${ + errors.duration_minutes + ? 'border-red-300 focus:border-red-500' + : 'border-slate-200 focus:border-slate-900' + } focus:outline-none`} + disabled={loading} + /> + {errors.duration_minutes && ( +

{errors.duration_minutes}

+ )} +
+
+ + {/* Capacity */} +
+ + setCapacity(parseInt(e.target.value) || 0)} + min="1" + className={`w-full px-4 py-3 border-2 rounded-lg font-medium transition-colors ${ + errors.capacity + ? 'border-red-300 focus:border-red-500' + : 'border-slate-200 focus:border-slate-900' + } focus:outline-none`} + disabled={loading} + /> + {errors.capacity && ( +

{errors.capacity}

+ )} +
+ + {/* Valid Date Range */} +
+
+ + setValidFrom(e.target.value)} + min={getTodayString()} + className={`w-full px-4 py-3 border-2 rounded-lg font-medium transition-colors ${ + errors.valid_from + ? 'border-red-300 focus:border-red-500' + : 'border-slate-200 focus:border-slate-900' + } focus:outline-none`} + disabled={loading} + /> + {errors.valid_from && ( +

{errors.valid_from}

+ )} +
+ +
+ + setValidTo(e.target.value)} + min={validFrom} + disabled={noEndDate || loading} + className={`w-full px-4 py-3 border-2 rounded-lg font-medium transition-colors ${ + errors.valid_to + ? 'border-red-300 focus:border-red-500' + : 'border-slate-200 focus:border-slate-900' + } focus:outline-none disabled:bg-slate-50 disabled:text-slate-400`} + /> + {errors.valid_to && ( +

{errors.valid_to}

+ )} + +
+
+ + {/* Description */} +
+ + setRuleDescription(e.target.value)} + placeholder="e.g., Monday morning regulars" + maxLength={200} + className="w-full px-4 py-3 border-2 border-slate-200 rounded-lg font-medium focus:border-slate-900 focus:outline-none transition-colors" + disabled={loading} + /> +

+ Helps you remember context for this slot definition +

+
+ + {/* Actions */} +
+ + +
+
+
+
+ ); +} diff --git a/src/app/[locale]/admin/clubs/[club_id]/slot-definitions/SlotDefinitionsComponent.tsx b/src/app/[locale]/admin/clubs/[club_id]/slot-definitions/SlotDefinitionsComponent.tsx index 3087587..a36e38d 100644 --- a/src/app/[locale]/admin/clubs/[club_id]/slot-definitions/SlotDefinitionsComponent.tsx +++ b/src/app/[locale]/admin/clubs/[club_id]/slot-definitions/SlotDefinitionsComponent.tsx @@ -4,20 +4,29 @@ import { useState, useEffect } from 'react'; import { Calendar, Plus, Loader2, AlertCircle, Edit, Trash2, ArrowLeft } from 'lucide-react'; import Link from 'next/link'; import useTranslation from '@/src/hooks/useTranslation'; -import { getSlotDefinitions, getMockSlotDefinitions } from '@/src/lib/api/slot-definitions'; +import { getSlotDefinitions, getMockSlotDefinitions, deleteSlotDefinition } from '@/src/lib/api/slot-definitions'; import type { SlotDefinition, SlotDefinitionError } from '@/src/types/slot-definitions'; import { DAY_NAMES, formatTime, calculateEndTime } from '@/src/types/slot-definitions'; +import SlotDefinitionForm from './SlotDefinitionForm'; interface SlotDefinitionsComponentProps { clubId: number; } +// Mock courts data (will come from parent/API later) +const MOCK_COURTS = [ + { court_id: 101, name: 'Court 1' }, + { court_id: 102, name: 'Court 2' }, + { court_id: 103, name: 'Court 3' }, +]; + export default function SlotDefinitionsComponent({ clubId }: SlotDefinitionsComponentProps) { const { t, locale } = useTranslation(); const [definitions, setDefinitions] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showCreateModal, setShowCreateModal] = useState(false); + const [editingDefinition, setEditingDefinition] = useState(undefined); useEffect(() => { loadDefinitions(); @@ -50,20 +59,35 @@ export default function SlotDefinitionsComponent({ clubId }: SlotDefinitionsComp } function handleCreate() { + setEditingDefinition(undefined); setShowCreateModal(true); } function handleEdit(definition: SlotDefinition) { - // TODO: Open edit modal - console.log('Edit', definition); + setEditingDefinition(definition); + setShowCreateModal(true); } async function handleDelete(definition: SlotDefinition) { if (!confirm(`Delete slot definition for ${DAY_NAMES[definition.dow]} at ${formatTime(definition.starts_at)}?`)) { return; } - // TODO: Call delete API - console.log('Delete', definition); + + const result = await deleteSlotDefinition(clubId, definition.slot_definition_id); + if (result.success) { + loadDefinitions(); + } else { + alert(`Failed to delete: ${result.error.detail}`); + } + } + + function handleFormClose() { + setShowCreateModal(false); + setEditingDefinition(undefined); + } + + function handleFormSuccess() { + loadDefinitions(); } // Loading state @@ -245,20 +269,15 @@ export default function SlotDefinitionsComponent({ clubId }: SlotDefinitionsComp )} - {/* TODO: Create/Edit Modal */} + {/* Create/Edit Modal */} {showCreateModal && ( -
-
-

Create Slot Definition

-

Form coming next...

- -
-
+ )} );