diff --git a/.coverage b/.coverage index 529c155..8a846dd 100644 Binary files a/.coverage and b/.coverage differ diff --git a/.hypothesis/examples/2cdee0278f1e8306/394341b7182cd227 b/.hypothesis/examples/2cdee0278f1e8306/394341b7182cd227 new file mode 100644 index 0000000..593f470 Binary files /dev/null and b/.hypothesis/examples/2cdee0278f1e8306/394341b7182cd227 differ diff --git a/.hypothesis/examples/ebb59080e4cf290d/394341b7182cd227 b/.hypothesis/examples/ebb59080e4cf290d/394341b7182cd227 new file mode 100644 index 0000000..593f470 Binary files /dev/null and b/.hypothesis/examples/ebb59080e4cf290d/394341b7182cd227 differ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 268cbf9..0dc8533 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,9 +2,20 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/psf/black - rev: 20.8b1 + rev: stable hooks: - id: black + args: # arguments to configure black + - --line-length=100 + - --exclude="""\.git | + \.__pycache__| + \.mypy_cache| + \.tox| + \.python-version| + _build| + build| + dist + """ description: "Formatting code" language: python language_version: 3.8.5 @@ -12,6 +23,10 @@ repos: rev: 3.8.4 hooks: - id: flake8 + args: # arguments to configure flake8 + - "--max-line-length=100" + - "--max-complexity=18" + - "--ignore=E203,E266,E501,W503,F403,F401,E402" description: "Styling guide enforcement" language: python language_version: 3.8.5 @@ -19,3 +34,7 @@ repos: rev: 'v0.790' hooks: - id: mypy +- repo: https://github.com/pre-commit/mirrors-isort + rev: '' # Use the revision sha / tag you want to point at + hooks: + - id: isort diff --git a/Makefile b/Makefile index 22e30d7..23170da 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ install: # install the dependencies test: # run test coverage @echo "testing ..." - ${RUN} pytest --cov=. --cov-report html + ${RUN} run pytest --cov=. --cov-report html --hypothesis-show-statistics quality: # run test, formating the code, check for typing, check if the code is safe @echo "check for linting, Typing, code formating, safety" diff --git a/ajo/home/home.py b/ajo/home/home.py index d68110d..9edd3aa 100644 --- a/ajo/home/home.py +++ b/ajo/home/home.py @@ -1,7 +1,11 @@ -from fastapi import APIRouter, Request +from datetime import date + +from fastapi import APIRouter, Form, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates +from .salary import Salary + router = APIRouter() templates = Jinja2Templates(directory="templates") @@ -10,3 +14,29 @@ @router.get("/home", response_class=HTMLResponse) async def home(request: Request): return templates.TemplateResponse("home.html", {"request": request}) + + +@router.post("/home", response_class=HTMLResponse) +async def home_form( + request: Request, + period: str = Form(...), + salary: int = Form(...), + start_date: date = Form(...), + mojo: float = Form(...), +): + + saving_type = Salary(salary=salary) + + return templates.TemplateResponse( + "home.html", + { + "request": request, + "period": period, + "salary": salary, + "start_date": start_date, + "mojo": mojo, + "smile": salary * saving_type.smile, + "maintenance": salary * saving_type.maintenance, + "mojo_progress": saving_type.mojo_progress(mojo), + }, + ) diff --git a/ajo/home/salary.py b/ajo/home/salary.py new file mode 100644 index 0000000..0e8047b --- /dev/null +++ b/ajo/home/salary.py @@ -0,0 +1,35 @@ +from dataclasses import dataclass +from typing import Union + + +@dataclass +class Salary: + salary: Union[float, int] + already_in_mojo: Union[float, int] = 0 + mojo: float = 0.2 + smile: float = 0.1 + maintenance: float = 0.1 + other: float = 0.6 + + @property + def check_salary(self) -> Union[int, float]: + """ + :return: zero should be returned + """ + if self.salary is None: + self.salary = 0 + return self.salary + + def mojo_progress(self, mojo_goal: Union[float, int]) -> float: + """ + :param mojo_goal: Amount you are aiming to attain + :return: Amount you currently have in your mojo account + """ + + self.salary = self.check_salary + + if not isinstance(self.salary, (int, float)): + raise ValueError("salary can either be integer or float") + + mojo_percent = self.salary * self.mojo * 100 + return self.already_in_mojo + mojo_percent / mojo_goal diff --git a/ajo/main.py b/ajo/main.py index 1263ae1..80f3353 100644 --- a/ajo/main.py +++ b/ajo/main.py @@ -4,6 +4,7 @@ from ajo.access import access from ajo.home import home from ajo.login import login +from ajo.setup import setup app = FastAPI() @@ -13,3 +14,4 @@ app.include_router(access.router) app.include_router(home.router) app.include_router(login.router) +app.include_router(setup.router) diff --git a/ajo/setup/__init__.py b/ajo/setup/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ajo/setup/setup.css b/ajo/setup/setup.css new file mode 100644 index 0000000..6a21c94 --- /dev/null +++ b/ajo/setup/setup.css @@ -0,0 +1,199 @@ +.container { + position: relative; + width: 100%; + height: 100%; + max-width: 800px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; +} + +/*-------header style--------*/ +header .field-header { + padding: 10px; +} + +header .field-header .user-name { + display: inline; + margin: 0 auto; + padding-top: 20px; + position: relative; +} + + select { + appearance: none; + border: none; + text-align: right; + text-transform: uppercase; + cursor: pointer; + font-size: 15px; + letter-spacing: 4px; + position: relative; + margin: 10px; + padding: 10px; + width: 200px; + text-align: right; + transition-duration: 0.4s; + overflow: hidden; + box-shadow: 0 5px 15px #149937; + float:right; +} + +select:after { + appearance: none; + border: none; +} + +select option { + appearance: none; + border: none; + background-color: transparent; +} + +/*------End: header style------*/ + +.container .section-row { + margin: 0 auto; + padding: 10px; +} +.container .section-row .field-row { + margin: 0 auto; + padding: 10px; +} + +fieldset { + padding: 20px; + border: 2px solid #149937; + border-radius: 10px; + box-shadow: 0 5px 10px greenyellow; +} + +/*----Start: legend style------*/ +.legend-header{ + font-size:large; + text-transform: uppercase; + cursor: pointer; + font-size: 15px; + } + +.legend-row { + text-transform: uppercase; + cursor: pointer; + font-size: 15px; + } + + +/*---End legend style----*/ + +/*-----Start: form text------*/ +input[type=text] { + border-radius: 5px; + width: 40%; + height: 30px; + border: 2px solid #149937; + +} +/*-----End: form text----------*/ + +/*-----Start: form date----------*/ +input[type=date] { + border-radius: 5px; + width: 40%; + height: 30px; + border: 2px solid #149937; + +} +/*-----End: form date--------------*/ + +/*------Start: form range----------------*/ +.container .section-row table .td-range { + width: 100%; +} + + input[type="range"] { + padding: 1px; + height: 35px; + width: 90%; + -webkit-appearance: none; +} + +input[type="range"]:focus { + outline: none; +} + +input[type=range]::-webkit-slider-runnable-track { + width: 90%; + height: 15px; + cursor: pointer; + animate: 0.2s; + background: transparent; + border-radius: 5px; + border: 2px solid #149937; +} + +input[type=range]::-webkit-slider-thumb { + box-shadow: 1px 1px 1px greenyellow; + border: 1px solid #149937; + height: 30px; + width: 30px; + border-radius: 15px; + background: yellowgreen; + cursor: pointer; + -webkit-appearance: none; + margin: -8px; +} +/*------End: form range----------------*/ + +/* -----form button ----------*/ +button[type=submit] { + appearance: none; +} + +button[type=submit] { + text-align: center; + text-transform: uppercase; + cursor: pointer; + font-size: 20px; + letter-spacing: 4px; + position: relative; + background-color: white; + border: solid #149937; + color: #149937; + margin: 10px; + padding: 10px; + width: 200px; + text-align: center; + transition-duration: 0.4s; + overflow: hidden; + box-shadow: 0 5px 15px #149937; + border-radius: 10px; + float: right; +} +button[type=submit]:hover { + background: #fff; + box-shadow: 0px 2px 10px 5px #1abc9c; + color: #000; +} + +button[type=submit]:after { + content: ""; + background: green; + display: block; + position: absolute; + padding-top: 300%; + padding-left: 350%; + margin-left: -20px !important; + margin-top: -120%; + opacity: 0; + transition: all 0.8s +} + +button[type=submit]:active:after { + padding: 0; + margin: 0; + opacity: 1; + transition: 0s +} + +button[type=submit]:focus { outline:0; } +/* -----form button ----------*/ diff --git a/ajo/setup/setup.html b/ajo/setup/setup.html new file mode 100644 index 0000000..424cf75 --- /dev/null +++ b/ajo/setup/setup.html @@ -0,0 +1,97 @@ + + + + + + + + + + + +
+
+
+

Hi {{}}!

+
+ +
+
+
+
+
+ Finance Configuration +
+
+
+ Period + +
+ +
+ +
+
+
+
+
+ Salary + +
+
+
+
+ Date + +
+
+
+
+ Set Mojo Target + +
+
+
+
+ Salary Percentage Split + + + + + + + + + + + + + + + + + + + + +
60%
20%
10%
10%
+
+
+
+ +
+
+
+
+ +
+
+ \ No newline at end of file diff --git a/ajo/setup/setup.py b/ajo/setup/setup.py new file mode 100644 index 0000000..d39c930 --- /dev/null +++ b/ajo/setup/setup.py @@ -0,0 +1,12 @@ +from fastapi import APIRouter, Request +from fastapi.responses import HTMLResponse +from fastapi.templating import Jinja2Templates + +router = APIRouter() + +templates = Jinja2Templates(directory="templates") + + +@router.get("/setup", response_class=HTMLResponse) +def setup(request: Request): + return templates.TemplateResponse("setup.html", {"request": request}) diff --git a/poetry.lock b/poetry.lock index e90ccc0..ef49a6f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -26,7 +26,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" name = "attrs" version = "20.3.0" description = "Classes Without Boilerplate" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" @@ -217,6 +217,34 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "hypothesis" +version = "6.0.3" +description = "A library for property-based testing" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +attrs = ">=19.2.0" +sortedcontainers = ">=2.1.0,<3.0.0" + +[package.extras] +all = ["black (>=19.10b0)", "click (>=7.0)", "django (>=2.2)", "dpcontracts (>=0.4)", "lark-parser (>=0.6.5)", "libcst (>=0.3.16)", "numpy (>=1.9.0)", "pandas (>=0.25)", "pytest (>=4.3)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "importlib-resources (>=3.3.0)", "importlib-metadata", "backports.zoneinfo (>=0.2.1)", "tzdata (>=2020.4)"] +cli = ["click (>=7.0)", "black (>=19.10b0)"] +codemods = ["libcst (>=0.3.16)"] +dateutil = ["python-dateutil (>=1.4)"] +django = ["pytz (>=2014.1)", "django (>=2.2)"] +dpcontracts = ["dpcontracts (>=0.4)"] +ghostwriter = ["black (>=19.10b0)"] +lark = ["lark-parser (>=0.6.5)"] +numpy = ["numpy (>=1.9.0)"] +pandas = ["pandas (>=0.25)"] +pytest = ["pytest (>=4.3)"] +pytz = ["pytz (>=2014.1)"] +redis = ["redis (>=3.0.0)"] +zoneinfo = ["importlib-resources (>=3.3.0)", "backports.zoneinfo (>=0.2.1)", "tzdata (>=2020.4)"] + [[package]] name = "identify" version = "1.5.11" @@ -478,6 +506,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.dependencies] pytest = ">=2.9.0" +[[package]] +name = "python-multipart" +version = "0.0.5" +description = "A streaming multipart parser for Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.4.0" + [[package]] name = "pyyaml" version = "5.3.1" @@ -530,7 +569,7 @@ requests = "*" name = "six" version = "1.15.0" description = "Python 2 and 3 compatibility utilities" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" @@ -542,6 +581,14 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "sortedcontainers" +version = "2.3.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "starlette" version = "0.13.6" @@ -667,7 +714,7 @@ python-versions = "*" [metadata] lock-version = "1.1" python-versions = "^3.8.5" -content-hash = "90215ae43b600592653992c7e2d1a321d68e74197c0409231a9a1466fe6ea6ac" +content-hash = "ff4e8eb26737bf29340c3a4e8964ed53b485735d132881fc9fb164dc17ec35ab" [metadata.files] aiofiles = [ @@ -796,6 +843,10 @@ h11 = [ {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, ] +hypothesis = [ + {file = "hypothesis-6.0.3-py3-none-any.whl", hash = "sha256:de3c21d89e2d9e36463a57706b411fad37158f2dc704e357b7f3b1ddd2669aa4"}, + {file = "hypothesis-6.0.3.tar.gz", hash = "sha256:c606c5141ea167a6893ffaea2647a263b93f8db6af28f58b526ce2edce08685a"}, +] identify = [ {file = "identify-1.5.11-py2.py3-none-any.whl", hash = "sha256:7aef7a5104d6254c162990e54a203cdc0fd202046b6c415bd5d636472f6565c4"}, {file = "identify-1.5.11.tar.gz", hash = "sha256:b2c71bf9f5c482c389cef816f3a15f1c9d7429ad70f497d4a2e522442d80c6de"}, @@ -955,6 +1006,9 @@ pytest-metadata = [ {file = "pytest-metadata-1.11.0.tar.gz", hash = "sha256:71b506d49d34e539cc3cfdb7ce2c5f072bea5c953320002c95968e0238f8ecf1"}, {file = "pytest_metadata-1.11.0-py2.py3-none-any.whl", hash = "sha256:576055b8336dd4a9006dd2a47615f76f2f8c30ab12b1b1c039d99e834583523f"}, ] +python-multipart = [ + {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, +] pyyaml = [ {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"}, {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"}, @@ -1029,6 +1083,10 @@ smmap = [ {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"}, ] +sortedcontainers = [ + {file = "sortedcontainers-2.3.0-py2.py3-none-any.whl", hash = "sha256:37257a32add0a3ee490bb170b599e93095eed89a55da91fa9f48753ea12fd73f"}, + {file = "sortedcontainers-2.3.0.tar.gz", hash = "sha256:59cc937650cf60d677c16775597c89a960658a09cf7c1a668f86e1e4464b10a1"}, +] starlette = [ {file = "starlette-0.13.6-py3-none-any.whl", hash = "sha256:bd2ffe5e37fb75d014728511f8e68ebf2c80b0fa3d04ca1479f4dc752ae31ac9"}, {file = "starlette-0.13.6.tar.gz", hash = "sha256:ebe8ee08d9be96a3c9f31b2cb2a24dbdf845247b745664bd8a3f9bd0c977fdbc"}, diff --git a/pyproject.toml b/pyproject.toml index ed66d82..bfd3a92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,8 @@ Jinja2 = "^2.11.2" aiofiles = "^0.6.0" uvicorn = "^0.13.3" requests = "^2.25.1" +python-multipart = "^0.0.5" +hypothesis = "^6.0.3" [tool.poetry.dev-dependencies] pytest = "^5.2" diff --git a/static/css/home.css b/static/css/home.css index 269c577..d027063 100644 --- a/static/css/home.css +++ b/static/css/home.css @@ -1,193 +1,115 @@ - -.header { - grid-area: hd; - border: 0.5px dashed; - -} - -.content-upper { - grid-area: main1; - border: 0.5px dashed; - border-radius: 10px; - margin: 2px; - padding: 5px; - -} - -.content-bottom { - grid-area: main2; - border: 0.5px dashed; - border-radius: 10px; - margin: 5px; - padding: 10px; -} - -.sidebar { - grid-area: sd; - border: 0.5px dashed; - border-radius: 10px; - margin: 5px; - padding: 10px; -} - -.footer { - grid-area: ft; - border: 0.5px dashed; -} - .container { - display: grid; - grid-template-columns: repeat(9, 1fr); - grid-auto-rows: minmax(100px, auto); - grid-template-areas: - "hd hd hd hd hd hd hd hd hd" - "sd sd sd main1 main1 main1 main1 main1 main1" - "sd sd sd main1 main1 main1 main1 main1 main1" - "sd sd sd main1 main1 main1 main1 main1 main1" - "sd sd sd main2 main2 main2 main2 main2 main2" - "sd sd sd main2 main2 main2 main2 main2 main2" - "sd sd sd main2 main2 main2 main2 main2 main2" - "sd sd sd main2 main2 main2 main2 main2 main2" - "ft ft ft ft ft ft ft ft ft"; - - height: 100vh; -} - -input[type="range"] { - padding: 1px; - height: 35px; - width: 80%; - -webkit-appearance: none; + position: relative; + width: 100%; + height: 100%; + max-width: 800px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } -input[type="range"]:focus { - outline: none; +.container header { + margin: 0 auto; + padding: 10px; } -input[type=range]::-webkit-slider-runnable-track { - width: 80%; - height: 15px; - cursor: pointer; - animate: 0.2s; - background: transparent; - border-radius: 5px; - border: 2px solid #149937; +.container header { + margin: 0 auto; + padding: 20px; } - -input[type=range]::-webkit-slider-thumb { - box-shadow: 1px 1px 1px greenyellow; - border: 1px solid #149937; - height: 30px; - width: 30px; - border-radius: 15px; - background: yellowgreen; - cursor: pointer; - -webkit-appearance: none; - margin: -8px; +header .field-header { + padding: 20px; } -.menu { - width: 11%; +.container header .menu { + width: 100%; height: 40px; padding-left: 5px; border-radius: 10px; - float: right; } -.menu ul, .menu li { + +header .menu ul { + display: inline; margin: 0 auto; - padding: 0; - list-style: none + padding: 0; + list-style: none; + float: right; } -.menu ul { - width: 100%; -} .menu li { - float: left; - display: inline; + display: inline; + margin: 0 auto; + padding: 10px; position: relative; } -.menu a { - display: block; - line-height: 45px; - padding: 0 14px; - text-decoration: none; - color: yellowgreen; - font-size: 16px; +header .field-header .user-name { + display: inline; + margin: 0 auto; + padding-top: 20px; + position: relative; } -.content-upper fieldset { - margin: 0.5%; - padding: 1%; - border: 2px solid greenyellow; - border-radius: 10px; -} - -.content-upper fieldset legend { - font-size:large; - font-weight: bold; - } -.content-upper table { - width: 100%; + select { + appearance: none; + border: none; + text-align: right; + text-transform: uppercase; + cursor: pointer; + font-size: 15px; + letter-spacing: 4px; + position: relative; + margin: 10px; + padding: 10px; + width: 200px; + text-align: right; + transition-duration: 0.4s; + overflow: hidden; + box-shadow: 0 5px 15px #149937; + float:right; } -.content-upper table .td-range { - width: 100%; -} -.sidebar fieldset { - margin: 1%; - padding: 23px; - border: 2px solid greenyellow; - border-radius: 10px; +.container .section-row { + margin: 0 auto; + padding: 10px; } -.sidebar fieldset legend { - width: 13; - font-weight: bold; - } - - .legend-header{ - font-size:large; - font-weight: bold; - } - - -.content-bottom fieldset { - margin: 1%; +fieldset { padding: 20px; - border: 2px solid greenyellow; + border: 1px solid #149937; border-radius: 10px; + overflow: hidden; + box-shadow: 0 5px 10px greenyellow; } -.content-bottom table { - width: 100%; -} +.legend-header{ + font-size:large; + text-transform: uppercase; + cursor: pointer; + overflow: hidden; + box-shadow: 0 5px 15px #222; + } -.content-bottom fieldset legend { - width: 13; - font-weight: bold; +.legend-row { + text-transform: uppercase; + overflow: hidden; + cursor: pointer; + font-size: 15px; + box-shadow: 0 5px 15px #222; } -.content-bottom p { - font-size: 25px; +.container .section-row table { + width: 100%; } - -input[type=text] { - border-radius: 5px; - height: 30px; - border: 2px solid #149937; - +.container .section-row table .comp-font { + width: 100%; + font-size: 60px; + } -input[type=date] { - border-radius: 5px; - border: 2px solid #149937; - -} progress[value] { -webkit-appearance: none; @@ -209,70 +131,6 @@ progress[value]::-webkit-progress-value::before { top: -125%; } -.flipswitch { - position:relative; - width: 86px; - float: right; -} -.flipswitch input[type=checkbox] { - display: none; -} -.flipswitch-label { - display: block; - overflow: hidden; - cursor: pointer; - border: 2px solid #149937; - border-radius: 50px; -} -.flipswitch-inner { - width: 200%; - margin-left: -100%; - transition: margin 0.3s ease-in 0s; -} -.flipswitch-inner:before, .flipswitch-inner:after { - float: left; - width: 50%; - height: 24px; - padding: 0; - line-height: 24px; - font-size: 18px; - color: white; - font-family: Trebuchet, Arial, sans-serif; - font-weight: bold; - box-sizing: border-box; -} -.flipswitch-inner:before { - content: "ON"; - padding-left: 12px; - background-color: whitesmoke; - color: #149937; -} -.flipswitch-inner:after { - content: "OFF"; - padding-right: 12px; - background-color: white; - color: #888888; - text-align: right; -} -.flipswitch-switch { - width: 31px; - margin: -3.5px; - background: #FAFAFA; - border: 2px solid #149937; - border-radius: 50px; - position: absolute; - top: 0; - bottom: 0; - right: 59px; - transition: all 0.3s ease-in 0s; -} -.flipswitch-cb:checked + .flipswitch-label .flipswitch-inner { - margin-left: 0; -} -.flipswitch-cb:checked + .flipswitch-label .flipswitch-switch { - right: 0; -} - -.header img { - width: 25; -} +img { + filter: drop-shadow(5px 5px 5px #222); +} \ No newline at end of file diff --git a/static/css/home_old.css b/static/css/home_old.css new file mode 100644 index 0000000..da3988a --- /dev/null +++ b/static/css/home_old.css @@ -0,0 +1,298 @@ + +.header { + grid-area: hd; + border: 0.5px dashed; + +} + +.content-upper { + grid-area: main1; + border: 0.5px dashed; + border-radius: 10px; + margin: 2px; + padding: 5px; + +} + +.content-bottom { + grid-area: main2; + border: 0.5px dashed; + border-radius: 10px; + margin: 5px; + padding: 10px; +} + +.sidebar { + grid-area: sd; + border: 0.5px dashed; + border-radius: 10px; + margin: 5px; + padding: 10px; +} + +.footer { + grid-area: ft; + border: 0.5px dashed; +} + +.container { + display: grid; + grid-template-columns: repeat(9, 1fr); + grid-auto-rows: minmax(100px, auto); + grid-template-areas: + "hd hd hd hd hd hd hd hd hd" + "sd sd sd main1 main1 main1 main1 main1 main1" + "sd sd sd main1 main1 main1 main1 main1 main1" + "sd sd sd main1 main1 main1 main1 main1 main1" + "sd sd sd main2 main2 main2 main2 main2 main2" + "sd sd sd main2 main2 main2 main2 main2 main2" + "sd sd sd main2 main2 main2 main2 main2 main2" + "sd sd sd main2 main2 main2 main2 main2 main2" + "ft ft ft ft ft ft ft ft ft"; + + height: 100vh; +} + +input[type="range"] { + padding: 1px; + height: 35px; + width: 80%; + -webkit-appearance: none; +} + +input[type="range"]:focus { + outline: none; +} + +input[type=range]::-webkit-slider-runnable-track { + width: 80%; + height: 15px; + cursor: pointer; + animate: 0.2s; + background: transparent; + border-radius: 5px; + border: 2px solid #149937; +} + +input[type=range]::-webkit-slider-thumb { + box-shadow: 1px 1px 1px greenyellow; + border: 1px solid #149937; + height: 30px; + width: 30px; + border-radius: 15px; + background: yellowgreen; + cursor: pointer; + -webkit-appearance: none; + margin: -8px; +} + +.menu { + width: 11%; + height: 40px; + padding-left: 5px; + border-radius: 10px; + float: right; +} + +.menu ul, .menu li { + margin: 0 auto; + padding: 0; + list-style: none +} + +.menu ul { + width: 100%; +} +.menu li { + float: left; + display: inline; + position: relative; +} + +.menu a { + display: block; + line-height: 45px; + line-height: 45px; + padding: 0 14px; + text-decoration: none; + color: yellowgreen; + font-size: 16px; +} +.content-upper fieldset { + margin: 0.5%; + padding: 1%; + border: 2px solid greenyellow; + border-radius: 10px; +} + +.content-upper fieldset legend { + font-size:large; + font-weight: bold; + } + +.content-upper table { + width: 100%; +} + +.content-upper table .td-range { + width: 100%; +} + +.sidebar fieldset { + margin: 1%; + padding: 23px; + border: 2px solid greenyellow; + border-radius: 10px; +} + +.sidebar fieldset legend { + width: 13; + font-weight: bold; + } + + .legend-header{ + font-size:large; + font-weight: bold; + } + + +.content-bottom fieldset { + margin: 1%; + padding: 20px; + border: 2px solid greenyellow; + border-radius: 10px; +} + +.content-bottom table { + width: 100%; +} + +.content-bottom fieldset legend { + width: 13; + font-weight: bold; + } + +.content-bottom p { + font-size: 25px; +} + + +input[type=text] { + border-radius: 5px; + height: 30px; + border: 2px solid #149937; + +} + +input[type=date] { + border-radius: 5px; + border: 2px solid #149937; + +} + +button[type=submit] { + appearance: none; +} + +button[type=submit] { + background-color: transparent; + margin: 20px; + width:250px; + height: 40px; + font-size: 20px; + color: #149937; + border: 2px solid yellowgreen; + border-radius: 10px; + float: right; +} + +progress[value] { + -webkit-appearance: none; + appearance: none; + width: 90%; + height: 50px; +} + +progress[value]::-webkit-progress-bar { + background-color: transparent; + border: 2px solid #149937; + border-radius: 5px; +} + +progress[value]::-webkit-progress-value::before { + content: '22%'; + position: absolute; + right: 0; + top: -125%; +} + +.header img { + width: 25; +} + +.button { + text-align: center; + text-transform: uppercase; + cursor: pointer; + font-size: 20px; + letter-spacing: 4px; + position: relative; + background-color: white; + border: solid green; + color: green; + padding: 20px; + width: 200px; + text-align: center; + transition-duration: 0.4s; + overflow: hidden; + box-shadow: 0 5px 15px #193047; + border-radius: 5px; +} + +.button:hover { + background: #fff; + box-shadow: 0px 2px 10px 5px #1abc9c; + color: #000; +} + +.button:after { + content: ""; + background: green; + display: block; + position: absolute; + padding-top: 300%; + padding-left: 350%; + margin-left: -20px !important; + margin-top: -120%; + opacity: 0; + transition: all 0.8s +} + +.button:active:after { + padding: 0; + margin: 0; + opacity: 1; + transition: 0s +} + +.button:focus { outline:0; } + + +img { + text-align: center; + text-transform: uppercase; + cursor: pointer; + font-size: 20px; + letter-spacing: 4px; + position: relative; + background-color: white; + border: solid green; + color: green; + padding: 20px; + width: 200px; + text-align: center; + transition-duration: 0.4s; + overflow: hidden; + box-shadow: 0 5px 15px #193047; + border-radius: 5px; +} \ No newline at end of file diff --git a/static/css/setup.css b/static/css/setup.css new file mode 100644 index 0000000..6a21c94 --- /dev/null +++ b/static/css/setup.css @@ -0,0 +1,199 @@ +.container { + position: relative; + width: 100%; + height: 100%; + max-width: 800px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; +} + +/*-------header style--------*/ +header .field-header { + padding: 10px; +} + +header .field-header .user-name { + display: inline; + margin: 0 auto; + padding-top: 20px; + position: relative; +} + + select { + appearance: none; + border: none; + text-align: right; + text-transform: uppercase; + cursor: pointer; + font-size: 15px; + letter-spacing: 4px; + position: relative; + margin: 10px; + padding: 10px; + width: 200px; + text-align: right; + transition-duration: 0.4s; + overflow: hidden; + box-shadow: 0 5px 15px #149937; + float:right; +} + +select:after { + appearance: none; + border: none; +} + +select option { + appearance: none; + border: none; + background-color: transparent; +} + +/*------End: header style------*/ + +.container .section-row { + margin: 0 auto; + padding: 10px; +} +.container .section-row .field-row { + margin: 0 auto; + padding: 10px; +} + +fieldset { + padding: 20px; + border: 2px solid #149937; + border-radius: 10px; + box-shadow: 0 5px 10px greenyellow; +} + +/*----Start: legend style------*/ +.legend-header{ + font-size:large; + text-transform: uppercase; + cursor: pointer; + font-size: 15px; + } + +.legend-row { + text-transform: uppercase; + cursor: pointer; + font-size: 15px; + } + + +/*---End legend style----*/ + +/*-----Start: form text------*/ +input[type=text] { + border-radius: 5px; + width: 40%; + height: 30px; + border: 2px solid #149937; + +} +/*-----End: form text----------*/ + +/*-----Start: form date----------*/ +input[type=date] { + border-radius: 5px; + width: 40%; + height: 30px; + border: 2px solid #149937; + +} +/*-----End: form date--------------*/ + +/*------Start: form range----------------*/ +.container .section-row table .td-range { + width: 100%; +} + + input[type="range"] { + padding: 1px; + height: 35px; + width: 90%; + -webkit-appearance: none; +} + +input[type="range"]:focus { + outline: none; +} + +input[type=range]::-webkit-slider-runnable-track { + width: 90%; + height: 15px; + cursor: pointer; + animate: 0.2s; + background: transparent; + border-radius: 5px; + border: 2px solid #149937; +} + +input[type=range]::-webkit-slider-thumb { + box-shadow: 1px 1px 1px greenyellow; + border: 1px solid #149937; + height: 30px; + width: 30px; + border-radius: 15px; + background: yellowgreen; + cursor: pointer; + -webkit-appearance: none; + margin: -8px; +} +/*------End: form range----------------*/ + +/* -----form button ----------*/ +button[type=submit] { + appearance: none; +} + +button[type=submit] { + text-align: center; + text-transform: uppercase; + cursor: pointer; + font-size: 20px; + letter-spacing: 4px; + position: relative; + background-color: white; + border: solid #149937; + color: #149937; + margin: 10px; + padding: 10px; + width: 200px; + text-align: center; + transition-duration: 0.4s; + overflow: hidden; + box-shadow: 0 5px 15px #149937; + border-radius: 10px; + float: right; +} +button[type=submit]:hover { + background: #fff; + box-shadow: 0px 2px 10px 5px #1abc9c; + color: #000; +} + +button[type=submit]:after { + content: ""; + background: green; + display: block; + position: absolute; + padding-top: 300%; + padding-left: 350%; + margin-left: -20px !important; + margin-top: -120%; + opacity: 0; + transition: all 0.8s +} + +button[type=submit]:active:after { + padding: 0; + margin: 0; + opacity: 1; + transition: 0s +} + +button[type=submit]:focus { outline:0; } +/* -----form button ----------*/ diff --git a/static/images/account.png b/static/images/account.png index 829a3b8..5c36c9d 100644 Binary files a/static/images/account.png and b/static/images/account.png differ diff --git a/static/images/download.png b/static/images/download.png index 31188ff..9990314 100644 Binary files a/static/images/download.png and b/static/images/download.png differ diff --git a/static/images/print.png b/static/images/print.png index f1f7bd8..02a9035 100644 Binary files a/static/images/print.png and b/static/images/print.png differ diff --git a/static/images/share.png b/static/images/share.png index bc8488d..71d20de 100644 Binary files a/static/images/share.png and b/static/images/share.png differ diff --git a/static/images_old/account.png b/static/images_old/account.png new file mode 100644 index 0000000..5c36c9d Binary files /dev/null and b/static/images_old/account.png differ diff --git a/static/images_old/download.png b/static/images_old/download.png new file mode 100644 index 0000000..9990314 Binary files /dev/null and b/static/images_old/download.png differ diff --git a/static/images/logo.png b/static/images_old/logo.png similarity index 100% rename from static/images/logo.png rename to static/images_old/logo.png diff --git a/static/images_old/print.png b/static/images_old/print.png new file mode 100644 index 0000000..02a9035 Binary files /dev/null and b/static/images_old/print.png differ diff --git a/static/images_old/share.png b/static/images_old/share.png new file mode 100644 index 0000000..71d20de Binary files /dev/null and b/static/images_old/share.png differ diff --git a/static/images/sign-off.png b/static/images_old/sign-off.png similarity index 100% rename from static/images/sign-off.png rename to static/images_old/sign-off.png diff --git a/static/js/home.js b/static/js/home.js index c60c284..efe809a 100644 --- a/static/js/home.js +++ b/static/js/home.js @@ -1,3 +1,7 @@ function updateRangeInput(val) { document.getElementById("mojoInput").value = val; } + +function updateRangeInput2(val) { + +} diff --git a/templates/home.html b/templates/home.html index 61d403d..1fbb49e 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,130 +1,87 @@ + - - - - + + + + + + +
-
- +
+
+

Welcome {{0}}!

+ +
-
+
- Salary Percentage Split + Target Outcome - - - - - - - - - - - - - - + + + -
60%
20%
10%
10% +
+ Start Date +

{{0}}

+
+
+
+ Next Contribution +

{{0}}

+
+
+
+ Mojo Last Date +

{{0}}

+
+
-
- -
-
-
- Target Outcome - - - +
- Mojo progress - + Mojo progress +
- Mojo Goal -

$0.0

+ Mojo Goal +

${{0}}

- Smile -

$0.0

+ Smile +

${{0}}

+
- Spouge -

$0.0

+ Maintenance +

${{0}}

-
- - +
diff --git a/templates/setup.html b/templates/setup.html new file mode 100644 index 0000000..3025228 --- /dev/null +++ b/templates/setup.html @@ -0,0 +1,97 @@ + + + + + + + + + + + +
+
+
+

Hi {{0}}!

+
+ +
+
+
+
+
+ Finance Configuration +
+
+
+ Period + +
+ +
+ +
+
+
+
+
+ Salary + +
+
+
+
+ Date + +
+
+
+
+ Set Mojo Target + +
+
+
+
+ Salary Percentage Split + + + + + + + + + + + + + + + + + + + + +
60%
20%
10%
10%
+
+
+
+ +
+
+
+
+ +
+
+ \ No newline at end of file diff --git a/tests/test_home.py b/tests/test_home.py new file mode 100644 index 0000000..4f7fa52 --- /dev/null +++ b/tests/test_home.py @@ -0,0 +1,58 @@ +import pytest +from hypothesis import given +from hypothesis.strategies import integers + +from ajo.home.salary import Salary + + +@given(salary=integers(1500, 4000), mojo_goal=integers(10000, 30000)) +def test_mojo_progress(salary, mojo_goal): + """ + GIVEN provided salary and saving_name as arguments to saving_split + WHEN saving_split is called + THEN it should return portion of salary for saving_name + """ + sal = Salary(salary=salary) + assert sal.mojo_progress(mojo_goal) == 0 + (salary * 0.2 * 100) / mojo_goal + + +def test_salary(): + """ + GIVEN None is provided as argument to class Salary + WHEN check_salary method is called + THEN return 0 + """ + salary = Salary(None) + assert salary.check_salary == 0 + + +def test_missing_salary(): + """ + GIVEN No argument is provided to class Salary + WHEN + THEN Raise TyperError + """ + with pytest.raises(TypeError, match=r"missing 1 required positional argument: 'salary'"): + Salary() + + +def test_mojo_progress_against_none(): + """ + GIVEN None is provided as argument to class Salary + WHEN mojo_progress is callled + THEN return 0 + """ + sal = Salary(salary=None) + mojo_goal = 10 + assert sal.mojo_progress(mojo_goal) == 0 + (0 * 0.2 * 100) / mojo_goal + + +def test_mojo_progress_against_string(): + """ + GIVEN String is provided as salary value to class Salary + WHEN mojo_progress method is called + THEN raise ValueError + """ + sal = Salary("Ade") + with pytest.raises(ValueError, match=r"salary can either be integer or float"): + sal.mojo_progress(10) diff --git a/tests/test_main.py b/tests/test_main.py index c77388a..35999c8 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -9,5 +9,10 @@ def test_login(test_main): def test_home(test_main): - response = test_main.get("/login") + response = test_main.get("/home") + assert response.status_code == 200 + + +def test_setup(test_main): + response = test_main.get("/setup") assert response.status_code == 200