|
@@ -1,375 +1,16 @@
|
|
import React from 'react' // React to manage the GUI
|
|
import React from 'react' // React to manage the GUI
|
|
-import Player from './classes/player'
|
|
|
|
-import Match from './classes/match'
|
|
|
|
|
|
+
|
|
|
|
+/** Import sub-modules */
|
|
|
|
+import startPage from './startPage'
|
|
import playerList from './playerList' // Everything that has to do with players
|
|
import playerList from './playerList' // Everything that has to do with players
|
|
import matchList from './matchList' // Everything that has to do with matches
|
|
import matchList from './matchList' // Everything that has to do with matches
|
|
-import Excel from './excel' // Helper files to create Excel files
|
|
|
|
-import { date2s, time2s } from './helpers'
|
|
|
|
-import 'bootstrap/dist/css/bootstrap.css'
|
|
|
|
-import EmailList from './lists/components/EmailList'
|
|
|
|
-import PhoneList from './lists/components/PhoneList'
|
|
|
|
import layout from './layout'
|
|
import layout from './layout'
|
|
|
|
|
|
-/**
|
|
|
|
- * General Application Design
|
|
|
|
- *
|
|
|
|
- * 4 Components:
|
|
|
|
- * - PlayerList (representing the PlayerList Excel file)
|
|
|
|
- * - Calendar (representing the Calendar Excel file)
|
|
|
|
- * - MatchList (representing the Spielliste Excel file)
|
|
|
|
- * - PaymentList (representing the Zahlliste Excel file)
|
|
|
|
- *
|
|
|
|
- * PlayerList
|
|
|
|
- * - Shows the relevant information from the file
|
|
|
|
- * - Shows calculated information from combination with Calendar
|
|
|
|
- * - Points out potential problems
|
|
|
|
- * - Allows access to player information
|
|
|
|
- *
|
|
|
|
- * Calendar
|
|
|
|
- * - Shows the relevant information from the file
|
|
|
|
- * - Shows calculated information from combination with PlayerList
|
|
|
|
- * - Points out potential problems
|
|
|
|
- * - Allows access to match information
|
|
|
|
- *
|
|
|
|
- * MatchList
|
|
|
|
- * - Shows the calculated match lists
|
|
|
|
- * - Points out problems
|
|
|
|
- *
|
|
|
|
- * PaymentList
|
|
|
|
- * - Shows the calculated payment lists
|
|
|
|
- * - Points out problems
|
|
|
|
- *
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
-const FILTER_OFF = 'Alle'
|
|
|
|
-const PLACES = {
|
|
|
|
- 'LE': 'TC Lerchenberg',
|
|
|
|
- 'WA': 'TC Waidberg',
|
|
|
|
- 'VA': 'TC Valsana',
|
|
|
|
- 'SE': 'TC Seebach',
|
|
|
|
- 'BU': 'TC Bührle',
|
|
|
|
- 'HO': 'TC Höngg',
|
|
|
|
- 'TS': 'Tennis-Sport Club',
|
|
|
|
- 'HA': 'Städtische Plätze Hardhof',
|
|
|
|
- 'AU': 'Auswärtig'
|
|
|
|
-}
|
|
|
|
|
|
+/** Import CSS Styles */
|
|
|
|
+import 'bootstrap/dist/css/bootstrap.css'
|
|
|
|
|
|
/** Main application */
|
|
/** Main application */
|
|
class Main extends React.Component {
|
|
class Main extends React.Component {
|
|
- /**
|
|
|
|
- * Constructor
|
|
|
|
- * Defines the state and binds all 'this' in all functions to the object.
|
|
|
|
- */
|
|
|
|
- constructor () {
|
|
|
|
- super()
|
|
|
|
-
|
|
|
|
- // Bind 'this' to functions
|
|
|
|
- this.handlePlayerList = this.handlePlayerList.bind(this)
|
|
|
|
- this.handleCalendar = this.handleCalendar.bind(this)
|
|
|
|
- this.generatePlayerList = this.generatePlayerList.bind(this)
|
|
|
|
- this.generateCalendar = this.generateCalendar.bind(this)
|
|
|
|
- this.filterMatches = this.filterMatches.bind(this)
|
|
|
|
- this.filterPlayers = this.filterPlayers.bind(this)
|
|
|
|
- this.generateSchedule = this.generateSchedule.bind(this)
|
|
|
|
- this.generatePayTable = this.generatePayTable.bind(this)
|
|
|
|
- this.generatePhoneList = this.generatePhoneList.bind(this)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- calculateMatchFilters () {
|
|
|
|
- const dates = {}
|
|
|
|
- const places = []
|
|
|
|
- const categories = []
|
|
|
|
- this.state.match.matches.forEach((item) => {
|
|
|
|
- const dateString = date2s(item.Datum)
|
|
|
|
- if (!!item.Datum & !dates.hasOwnProperty(dateString)) {
|
|
|
|
- dates[dateString] = item.Datum
|
|
|
|
- }
|
|
|
|
- if (!!item.Ort & !places.includes(item.Ort)) {
|
|
|
|
- places.push(item.Ort)
|
|
|
|
- }
|
|
|
|
- if (!!item.Konkurrenz & !categories.includes(item.Konkurrenz)) {
|
|
|
|
- categories.push(item.Konkurrenz)
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- const match = { ...this.state.match, dates, places, categories }
|
|
|
|
- this.setState({ match })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- calculatePlayerFilters () {
|
|
|
|
- const categories = []
|
|
|
|
- this.state.player.players.forEach((item) => {
|
|
|
|
- if (!!item.Konkurrenz & !categories.includes(item.Konkurrenz)) {
|
|
|
|
- categories.push(item.Ort)
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- const player = { ...this.state.player, categories }
|
|
|
|
- this.setState({ player })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- handlePlayerList (event) {
|
|
|
|
- const file = this.playerList.files[0]
|
|
|
|
- Excel.readWorkbook(file, this.generatePlayerList)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- handleCalendar (event) {
|
|
|
|
- const file = this.calendar.files[0]
|
|
|
|
- Excel.readWorkbook(file, this.generateCalendar)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- generatePlayerList (worksheet) {
|
|
|
|
- console.log('About to read the player list.')
|
|
|
|
- /* const worksheets = { ...this.state.worksheets }
|
|
|
|
- worksheets['PlayerList'] = worksheet
|
|
|
|
- this.setState({ worksheets }) */
|
|
|
|
-
|
|
|
|
- if (worksheet[4].length !== 32 & worksheet[3][0] !== 'Konkurrenz' & worksheet[3][31] !== 'bezahlt') {
|
|
|
|
- throw Error('Wrong file structure.')
|
|
|
|
- }
|
|
|
|
- const players = worksheet.slice(4, worksheet.length).map((playerData) => new Player.Player(playerData))
|
|
|
|
- const player = { ...this.state.player }
|
|
|
|
- player.players = players
|
|
|
|
- this.setState({ player })
|
|
|
|
- this.calculatePayDate()
|
|
|
|
- this.filterPlayers()
|
|
|
|
- console.log('State after generating player list:', this.state)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- generateCalendar (worksheet) {
|
|
|
|
- console.log('About to read the calendar.')
|
|
|
|
- const worksheets = { ...this.state.worksheets }
|
|
|
|
- worksheets['Calendar'] = worksheet
|
|
|
|
- this.setState({ worksheets })
|
|
|
|
-
|
|
|
|
- if (worksheet[2].length < 8 | worksheet[2].length > 9) {
|
|
|
|
- throw Error('Wrong file structure.')
|
|
|
|
- }
|
|
|
|
- const matches = worksheet.slice(2, worksheet.length).map((matchData) => new Match.MatchClass(matchData))
|
|
|
|
- const match = { ...this.state.match }
|
|
|
|
- match.matches = matches
|
|
|
|
- this.setState({ match })
|
|
|
|
- this.calculateMatchFilters()
|
|
|
|
- this.calculatePayDate()
|
|
|
|
- this.filterMatches()
|
|
|
|
- console.log('State after generating calendar:', this.state)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- filterMatches () {
|
|
|
|
- const filters = {
|
|
|
|
- date: this.matchDate.value !== FILTER_OFF ? this.matchDate.value : null,
|
|
|
|
- place: this.matchPlace.value !== FILTER_OFF ? this.matchPlace.value : null,
|
|
|
|
- category: this.matchCategory.value !== FILTER_OFF ? this.matchCategory.value : null
|
|
|
|
- }
|
|
|
|
- console.log('New filter settings:', filters)
|
|
|
|
-
|
|
|
|
- const match = { ...this.state.match }
|
|
|
|
- match.filtered = match.matches.filter((match) => {
|
|
|
|
- const matchDate = new Date(match.Datum)
|
|
|
|
- matchDate.setHours(0, 0, 0, 0)
|
|
|
|
- const filtDate = new Date(filters.date)
|
|
|
|
- filtDate.setHours(0, 0, 0, 0)
|
|
|
|
- return (!filters.date | matchDate.getTime() === filtDate.getTime()) &
|
|
|
|
- (!filters.place | filters.place === match.Ort) &
|
|
|
|
- (!filters.category | filters.category === match.Konkurrenz)
|
|
|
|
- })
|
|
|
|
- this.setState({ match })
|
|
|
|
-
|
|
|
|
- const player = { ...this.state.player, filters }
|
|
|
|
- player.filtered = player.players
|
|
|
|
- this.setState({ player })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- filterPlayers () {
|
|
|
|
- const filters = {
|
|
|
|
- junior: this.playerJunior.checked,
|
|
|
|
- paid: this.playerPaid.checked,
|
|
|
|
- category: this.playerCategory.value !== FILTER_OFF ? this.playerCategory.value : null
|
|
|
|
- }
|
|
|
|
- console.log('New filter settings:', filters)
|
|
|
|
-
|
|
|
|
- const player = { ...this.state.player, filters }
|
|
|
|
- player.filtered = player.players
|
|
|
|
- this.setState({ player })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- generateSchedule (event) {
|
|
|
|
- event.preventDefault()
|
|
|
|
-
|
|
|
|
- const matchlist = new Excel.Workbook()
|
|
|
|
- matchlist.SheetNames = []
|
|
|
|
- matchlist.Sheets = {}
|
|
|
|
-
|
|
|
|
- const worksheets = {}
|
|
|
|
-
|
|
|
|
- let placeArray = this.state.match.places
|
|
|
|
- if (placeArray.length > 1) {
|
|
|
|
- // placeArray = placeArray.concat([FILTER_OFF])
|
|
|
|
- }
|
|
|
|
- const date = Object.keys(this.state.match.dates).find((key) =>
|
|
|
|
- String(this.state.match.dates[key]) === this.matchDate.value
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- placeArray.forEach(place => {
|
|
|
|
- let header = [
|
|
|
|
- ['Stadtzürcher Tennismeisterschaft'],
|
|
|
|
- [`Spielplan für den ${date} (${PLACES[place] || place})`],
|
|
|
|
- [],
|
|
|
|
- ['Platz', 'Zeit', 'Kategorie', 'Spieler 1', '', 'Spieler 2', '', '1. Satz', '2. Satz', '3. Satz', 'WO Grund']
|
|
|
|
- ]
|
|
|
|
- let matchListPerPlace = this.state.match.filtered.filter((match) => (match.Ort === place | place === FILTER_OFF)).map((match) =>
|
|
|
|
- [null, time2s(match.Datum), match.Konkurrenz, match.Spieler1, match.Spieler1Klassierung, match.Spieler2, match.Spieler2Klassierung]
|
|
|
|
- )
|
|
|
|
- console.log('Generated match list per place:', matchListPerPlace)
|
|
|
|
- worksheets[place] = Excel.SheetFromArray(header.concat(matchListPerPlace))
|
|
|
|
- matchlist.SheetNames.push(place)
|
|
|
|
- matchlist.Sheets[place] = worksheets[place]
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- Excel.saveAs(matchlist, 'Spielplan.xlsx')
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- generatePhoneList (event) {
|
|
|
|
- event.preventDefault()
|
|
|
|
-
|
|
|
|
- const phoneMail = new Excel.Workbook()
|
|
|
|
- phoneMail.SheetNames = []
|
|
|
|
- phoneMail.Sheets = {}
|
|
|
|
-
|
|
|
|
- const dataList = [
|
|
|
|
- ['Vorname', 'Nachname', 'Anrede', 'Geschlecht', 'Handy', 'E-Mail']
|
|
|
|
- ]
|
|
|
|
- const phonePot = []
|
|
|
|
-
|
|
|
|
- const players = this.state.player.filtered
|
|
|
|
- players.forEach(player => {
|
|
|
|
- if (!player.phone.match(/^FEHLER/) && !phonePot.includes(player.phone)) {
|
|
|
|
- phonePot.push(player.phone)
|
|
|
|
- dataList.push([
|
|
|
|
- player.Vorname,
|
|
|
|
- player.Name,
|
|
|
|
- 2,
|
|
|
|
- player.geschlecht === 'w' ? 2 : 1,
|
|
|
|
- player.phone
|
|
|
|
- ])
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- phoneMail.Sheets['Sheet1'] = Excel.SheetFromArray(dataList)
|
|
|
|
- phoneMail.SheetNames.push('Sheet1')
|
|
|
|
- Excel.saveAs(phoneMail, 'Telefon.xlsx')
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- calculatePayDate () {
|
|
|
|
- if ((this.state.player.players.length === 0) | (this.state.match.matches.length === 0)) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this.state.match.matches.forEach((match) => {
|
|
|
|
- [match.Spieler1, match.Spieler2].forEach((matchPlayer) => {
|
|
|
|
- if (matchPlayer) {
|
|
|
|
- let foundPlayer = this.state.player.players.find((player) =>
|
|
|
|
- (player.name === matchPlayer) & (player.Konkurrenz === match.Konkurrenz)
|
|
|
|
- )
|
|
|
|
- if (!foundPlayer) {
|
|
|
|
- console.log('Debug payerlist:', foundPlayer, match)
|
|
|
|
- throw Error('Match player not found in player list. This is an error!')
|
|
|
|
- }
|
|
|
|
- if (!foundPlayer.BezahltAm) {
|
|
|
|
- foundPlayer.BezahltAm = match.Datum
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- generatePayTable (event) {
|
|
|
|
- event.preventDefault()
|
|
|
|
-
|
|
|
|
- const paylist = new Excel.Workbook()
|
|
|
|
- paylist.SheetNames = []
|
|
|
|
- paylist.Sheets = {}
|
|
|
|
-
|
|
|
|
- const worksheets = {}
|
|
|
|
-
|
|
|
|
- let placeArray = this.state.match.places
|
|
|
|
- /* if (placeArray.length > 1) {
|
|
|
|
- placeArray = placeArray.concat([FILTER_OFF])
|
|
|
|
- } */
|
|
|
|
- const date = Object.keys(this.state.match.dates).find((key) =>
|
|
|
|
- String(this.state.match.dates[key]) === this.matchDate.value
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- placeArray.forEach((place) => {
|
|
|
|
- let header = [
|
|
|
|
- ['Stadtzürcher Tennismeisterschaft'],
|
|
|
|
- [`Nenngelder für ${date}`],
|
|
|
|
- [],
|
|
|
|
- [`${PLACES[place] || place}`, null, '50.- oder 30.- (Junioren Jg. 1999 oder jünger)'],
|
|
|
|
- [],
|
|
|
|
- ['bezahlt', 'Kat.', 'Zeit', 'Name', 'Betrag bez.', 'Quittung']
|
|
|
|
- ]
|
|
|
|
-
|
|
|
|
- // Per place
|
|
|
|
- let payListPerPlace = []
|
|
|
|
- this.state.match.filtered.forEach((match) => {
|
|
|
|
- [match.Spieler1, match.Spieler2].forEach((matchPlayer) => {
|
|
|
|
- if (!!matchPlayer & (match.Ort === place | FILTER_OFF === place)) {
|
|
|
|
- const player = this.state.player.players.find((player) =>
|
|
|
|
- (player.Konkurrenz === match.Konkurrenz) & (player.name === matchPlayer)
|
|
|
|
- )
|
|
|
|
- let paid = null
|
|
|
|
- if (player.BezahltAm < this.matchDate.value) {
|
|
|
|
- paid = date2s(player.BezahltAm)
|
|
|
|
- }
|
|
|
|
- if (player.Bezahlt) {
|
|
|
|
- paid = 'OK'
|
|
|
|
- }
|
|
|
|
- let price
|
|
|
|
- if (player.isDoubles) {
|
|
|
|
- price = (player.isJunior ? 15 : 25) + (player.isJuniorDP ? 15 : 25)
|
|
|
|
- } else {
|
|
|
|
- price = player.isJunior ? 30 : 50
|
|
|
|
- }
|
|
|
|
- payListPerPlace.push([ paid, match.Konkurrenz, time2s(match.Datum), `(${price}.-) ${matchPlayer}` ])
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- let footer = [
|
|
|
|
- [],
|
|
|
|
- ['Datum'],
|
|
|
|
- ['Turnierleiter', null, null, 'Kassierer'],
|
|
|
|
- ['Betrag von Spielern erhalten', null, null, 'Betrag von Turnierleiter erhalten']
|
|
|
|
- ]
|
|
|
|
- console.log(`Generated pay list per place ${place}:`, payListPerPlace)
|
|
|
|
- worksheets[place] = Excel.SheetFromArray(header.concat(payListPerPlace, footer))
|
|
|
|
- paylist.SheetNames.push(place)
|
|
|
|
- paylist.Sheets[place] = worksheets[place]
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- /* let payListPerPlace = []
|
|
|
|
- this.state.match.filtered.forEach((match) => {
|
|
|
|
- [match.Spieler1, match.Spieler2].forEach((matchPlayer) => {
|
|
|
|
- if (matchPlayer) {
|
|
|
|
- const player = this.state.player.players.find((player) =>
|
|
|
|
- (player.Konkurrenz === match.Konkurrenz) & (player.name === matchPlayer)
|
|
|
|
- )
|
|
|
|
- let price
|
|
|
|
- if (player.isDoubles) {
|
|
|
|
- price = (player.isJunior ? 15 : 25) + (player.isJuniorDP ? 15 : 25)
|
|
|
|
- } else {
|
|
|
|
- price = player.isJunior ? 30 : 50
|
|
|
|
- }
|
|
|
|
- payListPerPlace.push([ match.Ort, match.Konkurrenz, `${matchPlayer} (${price}.-)` ])
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
- })
|
|
|
|
- console.log(`Generated pay list for "Alle":`, payListPerPlace)
|
|
|
|
- worksheets[FILTER_OFF] = Excel.SheetFromArray(payListPerPlace)
|
|
|
|
- paylist.SheetNames.push(FILTER_OFF)
|
|
|
|
- paylist.Sheets[FILTER_OFF] = worksheets[FILTER_OFF]
|
|
|
|
- */
|
|
|
|
- Excel.saveAs(paylist, 'Zahlliste.xlsx')
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
render () {
|
|
render () {
|
|
const AppLayout = layout.components.AppLayout
|
|
const AppLayout = layout.components.AppLayout
|
|
|
|
|
|
@@ -381,7 +22,8 @@ class Main extends React.Component {
|
|
state={this.props}
|
|
state={this.props}
|
|
components={{
|
|
components={{
|
|
PlayerList: playerList.components.PlayerList,
|
|
PlayerList: playerList.components.PlayerList,
|
|
- MatchTable: matchList.components.MatchTable
|
|
|
|
|
|
+ MatchTable: matchList.components.MatchTable,
|
|
|
|
+ StartPage: startPage.components.StartPage
|
|
}}
|
|
}}
|
|
/>
|
|
/>
|
|
</div>
|
|
</div>
|