diff --git a/README.md b/README.md index 5f1dae5..60e3186 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,9 @@ Open your browser to http://localhost:8000/ * Click 🏠 to go back to the main screen - * Progress the prize draw by pressing `spacebar` or `enter` or clicking in the middle of the screen. + * Draw a user by pressing `spacebar` or `enter` key. + + * Confirm the prize will be awarded by the drawn candidate by pressing the ➡️ or press ⬅️ to reject the prize draw. 'rejected' candidates will be marked has having been drawn but not awarded the prize. * Reset the prize draw by clicking ⚙️ then `FRESH IMPORT`. This will drop the existing database and re import from our data source into a fresh database. diff --git a/pyprize/admin.py b/pyprize/admin.py index f0cbb88..20bcca8 100644 --- a/pyprize/admin.py +++ b/pyprize/admin.py @@ -14,25 +14,23 @@ def index(): results = session.exec(statement) winners = [] + not_awarded = [] candidates = [] for candidate in results: if candidate.drawn_at is None: candidates.append(candidate) + elif candidate.awarded_prize is False: + not_awarded.append(candidate) else: winners.append(candidate) context = { - "winners": sorted(winners, key=lambda winner: winner.drawn_at), + "awarded": sorted(winners, key=lambda candidate: candidate.drawn_at), + "not_awarded": sorted( + not_awarded, key=lambda candidate: candidate.drawn_at + ), "candidates": candidates, } return render_template("admin/index.html", **context) - - -# @bp.get("/winners") -# def get_all_winners(): -# with Session(engine) as session: -# query = select(Candidate).where(Candidate.drawn_at != None) # noqa: E712 E501 -# winners = [winner.name for winner in session.exec(query).all()] -# return winners diff --git a/pyprize/core.py b/pyprize/core.py index e3ada18..4faee0a 100644 --- a/pyprize/core.py +++ b/pyprize/core.py @@ -1,5 +1,4 @@ -import json -from flask import Blueprint, render_template +from flask import Blueprint, render_template, jsonify, request from sqlmodel import delete, select, Session from sqlalchemy.sql import func @@ -49,13 +48,35 @@ def get_next(): results = session.exec(query) winner = results.first() + winner_json = winner.model_dump() + if winner: winner.mark_as_drawn() session.add(winner) session.commit() - return json.dumps({"name": winner.name, "feedback": ""}) + return jsonify({"candidate": winner_json, "feedback": ""}) else: - return json.dumps({"name": "", "feedback": "No winners left"}) + return jsonify({"candidate": "", "feedback": "No winners left"}) + + +@bp.post("/candidate//award") +def award(candidate_id: int): + award_prize = request.json.get("award_prize", False) + + with Session(engine) as session: + query = ( + select(Candidate).where(Candidate.id == candidate_id) # noqa: E711 + ) + results = session.exec(query) + candidate = results.first() + + if award_prize: + candidate.awarded_prize = True + + session.add(candidate) + session.commit() + + return ("OK", 200) @bp.get("/clear") diff --git a/pyprize/models.py b/pyprize/models.py index d467215..83bb355 100644 --- a/pyprize/models.py +++ b/pyprize/models.py @@ -14,13 +14,10 @@ class Candidate(SQLModel, table=True): def mark_as_drawn(self): self.drawn_at = datetime.now() - def mark_as_accepted(self): - self.drawn_at = datetime.now() + # TODO(iokiwi): + def award_prize(self, prize=None): self.awarded_prize = True - def mark_as_passed(self): - self.drawn_at = datetime.now() - class User(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) diff --git a/pyprize/static/js/admin.js b/pyprize/static/js/admin.js index fcd6d4a..0d9294b 100644 --- a/pyprize/static/js/admin.js +++ b/pyprize/static/js/admin.js @@ -6,6 +6,7 @@ jQuery(document).ready(function($){ type: 'GET', success: function (result) { $('#feedback').text(result); + window.location.reload(true); } }); }); @@ -15,7 +16,8 @@ jQuery(document).ready(function($){ url: '/clear', type: 'GET', success: function (result) { - $('#feedback').text(result); + $('#feedback').text(result); + window.location.reload(true); } }); }); diff --git a/pyprize/static/js/draw_candidates.js b/pyprize/static/js/draw_candidates.js index c9fc586..fb30065 100644 --- a/pyprize/static/js/draw_candidates.js +++ b/pyprize/static/js/draw_candidates.js @@ -3,6 +3,14 @@ const states = Object.freeze({ DRAWN: 1, }); +const KEYS = { + LEFT_ARROW: 37, + RIGHT_ARROW: 39, + ENTER: 13, + BACKSPACE: 8, + SPACE: 32, +}; + let state = states.CLEARED; function draw(){ @@ -10,9 +18,10 @@ function draw(){ url: '/next', type: 'GET', success: function (result) { - var res = JSON.parse(result); - $('#winner_name').html(res['name']); - $('#feedback').text(res['feedback']); + let winner_name = $("#winner_name") + winner_name.data("candidate", result.candidate.id); + winner_name.html(result.candidate.name); + $('#feedback').text(result.feedback); } }); state = states.DRAWN; @@ -23,20 +32,47 @@ function clear(){ state = states.CLEARED; } -function clear_or_draw(){ - if (state == states.CLEARED) { - draw(); - } else if (state == states.DRAWN) { - clear(); - } +function award_prize(action){ + let winner_name = $("#winner_name") + let candidate_id = winner_name.data("candidate") + $.ajax({ + url: `/candidate/${candidate_id}/award`, + type: 'POST', + contentType: 'application/json', + data: JSON.stringify({ + award_prize: action + }), + success: function (result) { + // Do nothing + // $('#feedback').text(result.feedback); + } + }) + clear() } -jQuery(document).ready(function($){ - $(document).on('keydown', function(e) { - // on spacebar or enter - if (e.which === 32 || e.which === 13) { - e.preventDefault(); - clear_or_draw() + +jQuery(document).ready(function() { + $(document).on('keydown', function(e){ + e.preventDefault() + + if (state === states.CLEARED) { + if ([KEYS.ENTER, KEYS.SPACE].includes(e.which)) { + draw() + } + } else if (state === states.DRAWN) { + if ([KEYS.LEFT_ARROW, KEYS.BACKSPACE].includes(e.which)) { + // award_prize(false) + // Actually nothing needs to be done here + clear() + } else if ([KEYS.RIGHT_ARROW, KEYS.ENTER].includes(e.which)) { + award_prize(true) + } } - }); -}); + } +)}) + + +// var handleSubmit = function(event) { +// event.preventDefault(); +// let challengeDiv = $(event.target).closest('.challenge'); +// let challengeNumber = challengeDiv.data("challengenumber"); diff --git a/pyprize/templates/admin/index.html b/pyprize/templates/admin/index.html index 9b0a01f..401f193 100644 --- a/pyprize/templates/admin/index.html +++ b/pyprize/templates/admin/index.html @@ -6,28 +6,36 @@ Fresh Import
Clear Database
-

Winners

+

Prizes Awarded

- {% for winner in winners %} + {% for candidate in awarded %} - - + + + {% endfor %}
{{ winner.drawn_at }}{{ winner.name }}{{ candidate.drawn_at }}{{ candidate.awarded_prize }}{{ candidate.name }}
-

Candidate Pool

+

Drawn but not Awarded

+ + + {% for candidate in not_awarded %} + + + + + + {% endfor %} +
{{ candidate.drawn_at }}{{ candidate.awarded_prize }}{{ candidate.name }}
+ +

Candidates not Drawn

- - diff --git a/pyprize/templates/base.html b/pyprize/templates/base.html index b2068d9..35dbc04 100644 --- a/pyprize/templates/base.html +++ b/pyprize/templates/base.html @@ -8,7 +8,7 @@ - + @@ -17,6 +17,6 @@ {% endblock %} - +