-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Feature/#80 trade modal
- Loading branch information
Showing
9 changed files
with
356 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { Render } from '../utils/Render'; | ||
import { pull } from 'lodash'; | ||
|
||
export abstract class EmptyModal { | ||
modal: HTMLElement; | ||
modalContainer: HTMLElement; | ||
constructor() { | ||
this.modalContainer = Render.elementFactory('div', { | ||
className: 'modal__container', | ||
}); | ||
this.modal = Render.elementFactory( | ||
'div', | ||
{ className: 'modal' }, | ||
this.modalContainer, | ||
); | ||
} | ||
|
||
/** | ||
* Hides modal - adds class with display:none | ||
*/ | ||
protected hideModal(): void { | ||
this.modal.classList.add('modal--hidden'); | ||
} | ||
|
||
/** | ||
* Shows modal - removes class with display:none | ||
*/ | ||
protected showModal(): void { | ||
this.modal.classList.remove('modal--hidden'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
import { AnimalNames } from '~src/Enums/AnimalNamesEnum'; | ||
import { Player } from '~src/Player'; | ||
import { Herd } from '../logic/Herd'; | ||
import { Offer, Trade } from '../Trade'; | ||
import { Render } from '../utils/Render'; | ||
import { EmptyModal } from './EmptyModal'; | ||
|
||
export class TradeModal extends EmptyModal { | ||
tradeForm: HTMLElement; | ||
playerView: HTMLElement; | ||
bankView: HTMLElement; | ||
warning: HTMLElement; | ||
backButton: HTMLElement; | ||
player: Player; | ||
|
||
constructor(private trade: Trade, firstPlayer: Player) { | ||
super(); | ||
this.player = firstPlayer; | ||
this.playerView = Render.elementFactory('div', { | ||
className: 'trade__player-wrapper', | ||
}); | ||
this.bankView = Render.elementFactory('div', { | ||
className: 'trade__player-wrapper', | ||
}); | ||
this.tradeForm = Render.elementFactory( | ||
'form', | ||
{ | ||
action: '', | ||
method: 'post', | ||
className: 'trade', | ||
}, | ||
this.playerView, | ||
Render.elementFactory('input', { | ||
type: 'submit', | ||
value: 'Trade', | ||
className: 'trade__submit', | ||
}), | ||
this.bankView, | ||
); | ||
this.warning = Render.elementFactory('p', { | ||
className: 'warning', | ||
}); | ||
this.backButton = Render.elementFactory('button', {}, 'back'); | ||
Render.childrenInjector( | ||
this.modalContainer, | ||
this.tradeForm, | ||
this.warning, | ||
this.backButton, | ||
); | ||
} | ||
|
||
/** | ||
* Creates TradeModal and returns it as HTMLElement. | ||
*/ | ||
createModal(): HTMLElement { | ||
Render.childrenInjector( | ||
this.bankView, | ||
this.createHerdView(this.trade.thisBank, true), | ||
); | ||
Render.childrenInjector( | ||
this.playerView, | ||
this.createHerdView(this.player), | ||
); | ||
this.tradeForm.addEventListener('submit', this.handleSubmit); | ||
this.modal.addEventListener('keydown', this.clearWarning); | ||
this.modal.addEventListener('click', this.clearWarning); | ||
this.backButton.addEventListener('click', () => this.hideModal()); | ||
return this.modal; | ||
} | ||
|
||
/** | ||
* Sets next player and his herd in the TradeModal. | ||
*/ | ||
setNextPlayer(player: Player): void { | ||
this.player = player; | ||
Render.removeAllChildren(this.playerView); | ||
this.playerView.appendChild(this.createHerdView(this.player)); | ||
this.updateBank(); | ||
this.showModal(); | ||
} | ||
|
||
private updateBank(): void { | ||
Render.removeAllChildren(this.bankView); | ||
this.bankView.appendChild( | ||
this.createHerdView(this.trade.thisBank, true), | ||
); | ||
} | ||
|
||
private createHerdView( | ||
{ theHerd: herd, theName: name }: Player, | ||
isBank = false, | ||
): HTMLElement { | ||
const herdElement = Render.elementFactory( | ||
'div', | ||
{ | ||
className: 'trade__player-herd', | ||
}, | ||
...this.generateAnimalRows(herd, isBank), | ||
); | ||
const container = Render.elementFactory( | ||
'div', | ||
{ | ||
className: 'trade__player', | ||
}, | ||
Render.elementFactory( | ||
'H2', | ||
{ className: 'trade__player-heading' }, | ||
`${name}`, | ||
), | ||
herdElement, | ||
); | ||
return container; | ||
} | ||
|
||
private generateAnimalRows( | ||
herd: Herd, | ||
isBank: boolean, | ||
): HTMLElement[] { | ||
const animalsRows: HTMLElement[] = herd.theAnimals.reduce( | ||
(animalsElements: HTMLElement[], [animal, count]) => { | ||
if (count > 0) { | ||
animalsElements.push( | ||
Render.elementFactory( | ||
'div', | ||
{ className: 'trade__row' }, | ||
Render.elementFactory( | ||
'label', | ||
{ | ||
for: `${isBank ? 'bank' : 'player'}_${ | ||
animal.theName | ||
}`, | ||
}, | ||
`${animal.theName}: ${count}`, | ||
), | ||
Render.elementFactory('input', { | ||
type: 'number', | ||
id: `${isBank ? 'bank' : 'player'}_${animal.theName}`, | ||
name: `${isBank ? 'bank' : 'player'}_${ | ||
animal.theName | ||
}`, | ||
min: '0', | ||
max: `${count}`, | ||
}), | ||
), | ||
); | ||
} | ||
return animalsElements; | ||
}, | ||
[], | ||
); | ||
|
||
return animalsRows; | ||
} | ||
|
||
private formDataIntoTuples(formData: FormData): [Offer[], Offer[]] { | ||
const offer: Offer[] = []; | ||
const target: Offer[] = []; | ||
for (const [key, value] of formData.entries()) { | ||
const numberOfAnimals = parseInt(value.toString()); | ||
const [player, animal] = key.split('_'); | ||
if (numberOfAnimals > 0) { | ||
switch (player) { | ||
case 'player': { | ||
offer.push([animal as AnimalNames, numberOfAnimals]); | ||
break; | ||
} | ||
case 'bank': { | ||
target.push([animal as AnimalNames, numberOfAnimals]); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
return [offer, target]; | ||
} | ||
|
||
private processTrade([offer, target]: [Offer[], Offer[]]): boolean { | ||
if (offer.length === 1 && target.length === 1) { | ||
const [[offeredAnimal]] = offer; | ||
const [[targetAnimal]] = target; | ||
if (this.trade.processOffer(offer[0], this.player, target[0])) { | ||
return true; | ||
} | ||
this.displayWarning( | ||
`The value ratio of the ${offeredAnimal}s to ${targetAnimal}s is not correct`, | ||
); | ||
return false; | ||
} | ||
if (offer.length > 1 || target.length > 1) { | ||
this.displayWarning( | ||
'To much types of animals, allowed one type for one type', | ||
); | ||
return false; | ||
} | ||
if (offer.length <= 0 || target.length <= 0) { | ||
this.displayWarning( | ||
'There need to be at least one animal on both sides', | ||
); | ||
return false; | ||
} | ||
return false; | ||
} | ||
|
||
private displayWarning(message: string): void { | ||
this.warning.textContent = message; | ||
} | ||
|
||
private handleSubmit = (event: Event): void => { | ||
event.preventDefault(); | ||
const formData = new FormData(event.target as HTMLFormElement); | ||
const data = this.formDataIntoTuples(formData); | ||
if (this.processTrade(data)) { | ||
this.hideModal(); | ||
} | ||
}; | ||
|
||
private clearWarning = (): void => { | ||
this.warning.textContent = ''; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { AnimalNames } from '~src/Enums/AnimalNamesEnum'; | ||
import { Player } from '~src/Player'; | ||
import { TradeModal } from '../components/TradeModal'; | ||
import { Bank } from '../logic/Bank'; | ||
import { Trade } from '../Trade'; | ||
import { Render } from '../utils/Render'; | ||
|
||
//type TradeModalDemo.playDemo() in init in App.ts | ||
export class TradeModalDemo { | ||
static playDemo(): void { | ||
const trade = new Trade(new Bank()); | ||
const player = new Player( | ||
'Donald', | ||
'./static/images/avatars/dog.png', | ||
); | ||
player.theHerd.addAnimalsToHerd(AnimalNames.RABBIT, 20); | ||
player.theHerd.addAnimalsToHerd(AnimalNames.SHEEP, 5); | ||
player.theHerd.addAnimalsToHerd(AnimalNames.PIG, 5); | ||
player.theHerd.addAnimalsToHerd(AnimalNames.COW, 2); | ||
player.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 1); | ||
const modal = new TradeModal(trade, player); | ||
Render.render('#sf-app', modal.createModal()); | ||
|
||
const player2 = new Player( | ||
'Gerwazy', | ||
'./static/images/avatars/dog.png', | ||
); | ||
player2.theHerd.addAnimalsToHerd(AnimalNames.RABBIT, 6); | ||
player2.theHerd.addAnimalsToHerd(AnimalNames.SHEEP, 1); | ||
player2.theHerd.addAnimalsToHerd(AnimalNames.PIG, 2); | ||
player2.theHerd.addAnimalsToHerd(AnimalNames.COW, 1); | ||
player2.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 1); | ||
|
||
const player3 = new Player( | ||
'Eustachy', | ||
'./static/images/avatars/dog.png', | ||
); | ||
player3.theHerd.addAnimalsToHerd(AnimalNames.RABBIT, 8); | ||
player3.theHerd.addAnimalsToHerd(AnimalNames.SHEEP, 3); | ||
player3.theHerd.addAnimalsToHerd(AnimalNames.PIG, 1); | ||
player3.theHerd.addAnimalsToHerd(AnimalNames.COW, 2); | ||
player3.theHerd.addAnimalsToHerd(AnimalNames.HORSE, 0); | ||
|
||
setTimeout(() => { | ||
modal.setNextPlayer(player2); | ||
setTimeout(() => modal.setNextPlayer(player3), 15000); | ||
}, 15000); | ||
} | ||
} |
Oops, something went wrong.