Initial commit, basic login working

This commit is contained in:
Lance Edgar 2023-09-22 21:39:25 -05:00
commit cbab5ec976
18 changed files with 913 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
WuttaPOS.egg-info/

10
CHANGELOG.md Normal file
View file

@ -0,0 +1,10 @@
# Changelog
All notable changes to WuttaPOS will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [0.1.0] - ??
### Added
- Initial version (not yet released)

4
README.md Normal file
View file

@ -0,0 +1,4 @@
# WuttaPOS
Why not write a new POS system..? Heh surely a terrible idea, yet here we are.

43
setup.cfg Normal file
View file

@ -0,0 +1,43 @@
# -*- coding: utf-8; -*-
[metadata]
name = WuttaPOS
version = attr: wuttapos.__version__
author = Lance Edgar
author_email = lance@edbob.org
url = https://rattailproject.org/
license = GNU GPL v3
description = Pythonic Point of Sale System
long_description = file: README.md
classifiers =
Development Status :: 3 - Alpha
Environment :: Win32 (MS Windows)
Environment :: X11 Applications
Intended Audience :: Developers
License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Natural Language :: English
Operating System :: OS Independent
Programming Language :: Python
Programming Language :: Python :: 3
Topic :: Office/Business :: Financial :: Point-Of-Sale
[options]
install_requires =
flet
psycopg2
rattail[db]
packages = find:
include_package_data = True
# zip_safe = False
[options.entry_points]
console_scripts =
wuttapos = wuttapos.commands:main
wuttapos.commands =
open = wuttapos.commands:Open
status = wuttapos.commands:Status

29
setup.py Normal file
View file

@ -0,0 +1,29 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS setup script
"""
from setuptools import setup
setup()

49
tasks.py Normal file
View file

@ -0,0 +1,49 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Tasks for WuttaPOS
"""
import os
import shutil
from invoke import task
here = os.path.abspath(os.path.dirname(__file__))
exec(open(os.path.join(here, 'wuttapos', '_version.py')).read())
@task
def release(c):
"""
Release a new version of WuttaPOS
"""
# rebuild local tar.gz file for distribution
if os.path.exists('WuttaPOS.egg-info'):
shutil.rmtree('WuttaPOS.egg-info')
c.run('python -m build --sdist')
# upload to PyPI
filename = f'WuttaPOS-{__version__}.tar.gz'
c.run(f'twine upload dist/{filename}')

27
wuttapos/__init__.py Normal file
View file

@ -0,0 +1,27 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - package root
"""
from ._version import __version__

3
wuttapos/_version.py Normal file
View file

@ -0,0 +1,3 @@
# -*- coding: utf-8; -*-
__version__ = '0.1.0'

115
wuttapos/app.py Normal file
View file

@ -0,0 +1,115 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS app
"""
import json
import os
from rattail.config import make_config
import flet as ft
import wuttapos
def main(page: ft.Page):
config = make_config()
page.title = f"WuttaPOS v{wuttapos.__version__}"
page.window_full_screen = True
# page.vertical_alignment = ft.MainAxisAlignment.CENTER
# nb. track current user, txn etc.
page.shared = {}
# TODO: this may be too hacky but is useful for now/dev
if not config.production():
path = os.path.join(config.appdir(), '.wuttapos.cache')
if os.path.exists(path):
with open(path, 'rt') as f:
page.shared = json.loads(f.read())
def clean_exit():
if not config.production():
# TODO: this may be too hacky but is useful for now/dev
path = os.path.join(config.appdir(), '.wuttapos.cache')
with open(path, 'wt') as f:
f.write(json.dumps(page.shared))
page.window_destroy()
def keyboard(e):
# exit on ctrl+Q
if e.ctrl and e.key == 'Q':
if not e.shift and not e.alt and not e.meta:
clean_exit()
page.on_keyboard_event = keyboard
def window_event(e):
if e.data == 'close':
clean_exit()
# cf. https://flet.dev/docs/controls/page/#window_destroy
page.window_prevent_close = True
page.on_window_event = window_event
# TODO: probably these should be auto-loaded from spec
from wuttapos.views.pos import POSView
from wuttapos.views.login import LoginView
# cf .https://flet.dev/docs/guides/python/navigation-and-routing#building-views-on-route-change
def route_change(route):
page.views.clear()
if page.route == '/pos':
page.views.append(POSView(config, '/pos'))
elif page.route == '/login':
page.views.append(LoginView(config, '/login'))
page.update()
# TODO: this was in example docs but not sure what it's for?
# def view_pop(view):
# page.views.pop()
# top_view = page.views[-1]
# page.go(top_view.route)
page.on_route_change = route_change
# page.on_view_pop = view_pop
# TODO: this may be too hacky but is useful for now/dev
if not config.production() and page.shared.get('user_uuid'):
page.go('/pos')
else:
page.go('/login')
# TODO: can we inject config to the main() via ft.app() kwargs somehow?
# pretty sure the `wuttapos open` command is trying to anyway..
def run_app(config=None):
ft.app(target=main)
if __name__ == '__main__':
run_app()

74
wuttapos/commands.py Normal file
View file

@ -0,0 +1,74 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS commands
"""
import sys
from rattail import commands
from wuttapos import __version__
def main(*args):
"""
Main entry point for WuttaPOS command system
"""
args = list(args or sys.argv[1:])
cmd = Command()
cmd.run(*args)
class Command(commands.Command):
"""
Top-level command for WuttaPOS
"""
name = 'wuttapos'
version = __version__
description = "WuttaPOS (point of sale)"
long_description = ''
class Open(commands.Subcommand):
"""
Open the Point of Sale app
"""
name = 'open'
description = __doc__.strip()
def run(self, args):
from wuttapos.app import run_app
run_app(self.config)
class Status(commands.Subcommand):
"""
Show status of the POS lane
"""
name = 'status'
description = __doc__.strip()
def run(self, args):
print("TODO: show status")

View file

@ -0,0 +1,25 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - flet controls
"""

35
wuttapos/controls/base.py Normal file
View file

@ -0,0 +1,35 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - custom controls (base class)
"""
import flet as ft
class WuttaControl(ft.UserControl):
def __init__(self, config, *args, **kwargs):
super().__init__(*args, **kwargs)
self.config = config
self.app = config.get_app()

View file

@ -0,0 +1,88 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - header control
"""
import flet as ft
from .base import WuttaControl
from .timestamp import WuttaTimestamp
class WuttaHeader(WuttaControl):
def build(self):
self.txn_display = ft.Text("Txn: N", weight=ft.FontWeight.BOLD, size=20)
self.user_display = ft.Text("User: N", weight=ft.FontWeight.BOLD, size=20)
self.logout_button = ft.FilledButton("Logout", on_click=self.logout_click, visible=False)
self.logout_divider = ft.VerticalDivider(visible=False)
controls = [
self.txn_display,
ft.VerticalDivider(),
ft.Text(f"Cust: N", weight=ft.FontWeight.BOLD, size=20),
ft.VerticalDivider(),
WuttaTimestamp(self.config, expand=True,
weight=ft.FontWeight.BOLD, size=20),
self.user_display,
ft.VerticalDivider(),
self.logout_button,
self.logout_divider,
ft.Text(f"WuttaPOS", weight=ft.FontWeight.BOLD, size=20),
]
return ft.Row(controls)
def did_mount(self):
self.update_txn_display()
self.update_user_display()
self.update()
def update_txn_display(self):
txn_display = "N"
if self.page and self.page.shared and self.page.shared.get('txn_display'):
txn_display = self.page.shared['txn_display']
self.txn_display.value = f"Txn: {txn_display}"
def update_user_display(self):
user_display = "N"
if self.page and self.page.shared and self.page.shared.get('user_display'):
user_display = self.page.shared['user_display']
self.user_display.value = f"User: {user_display}"
if self.page and self.page.shared.get('user_uuid'):
self.logout_button.visible = True
self.logout_divider.visible = True
def logout_click(self, e):
self.page.shared.update({
'user_uuid': None,
'user_display': None,
'txn_display': None,
})
self.page.go('/login')

View file

@ -0,0 +1,59 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - timestamp control
"""
import threading
import time
import flet as ft
from .base import WuttaControl
class WuttaTimestamp(WuttaControl):
def __init__(self, *args, **kwargs):
self.weight = kwargs.pop('weight', None)
self.size = kwargs.pop('size', None)
super().__init__(*args, **kwargs)
def build(self):
text = self.render_time(self.app.localtime())
self.display = ft.Text(text, weight=self.weight, size=self.size)
thread = threading.Thread(target=self.update_display)
thread.start()
return self.display
def render_time(self, value):
return value.strftime('%a %d %b %Y %I:%M:%S %p')
def update_display(self):
while True:
if self.page:
self.display.value = self.render_time(self.app.localtime())
self.update()
time.sleep(0.5)

View file

@ -0,0 +1,25 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - flet views
"""

74
wuttapos/views/base.py Normal file
View file

@ -0,0 +1,74 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - flet views (base class)
"""
import flet as ft
from wuttapos.controls.header import WuttaHeader
class WuttaView(ft.View):
"""
Base class for all Flet views used in WuttaPOS
"""
def __init__(self, config, *args, **kwargs):
super().__init__(*args, **kwargs)
self.config = config
self.app = self.config.get_app()
self.model = self.app.model
controls = self.build_controls()
self.controls = [
WuttaViewContainer(self.config,
content=ft.Column(controls=controls),
expand=True),
]
def build_controls(self):
return [self.build_header()]
def build_header(self):
return WuttaHeader(self.config)
class WuttaViewContainer(ft.Container):
"""
Main container class to wrap all controls for a view. Used for
displaying background image etc.
"""
def __init__(self, config, *args, **kwargs):
self.config = config
if 'image_src' not in kwargs and not self.config.production():
# TODO: host a local testing image? where *should* this come from?
image = self.config.get('rattail', 'testing_watermark')
if image:
kwargs['image_src'] = image
kwargs.setdefault('image_repeat', ft.ImageRepeat.REPEAT)
super().__init__(*args, **kwargs)

150
wuttapos/views/login.py Normal file
View file

@ -0,0 +1,150 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - login view
"""
import flet as ft
from .base import WuttaView
class LoginView(WuttaView):
"""
Main POS view for WuttaPOS
"""
def __init__(self, *args, **kwargs):
# TODO: maybe support setting this to False? for now that's not 100% supported
self.show_username = kwargs.pop('show_username', True)
super().__init__(*args, **kwargs)
def build_controls(self):
controls = [
ft.Row(
[ft.Text(value="Welcome to WuttaPOS", weight=ft.FontWeight.BOLD, size=28)],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(),
ft.Row(),
ft.Row(),
]
if self.show_username:
self.username = ft.TextField(label="Login", width=200,
on_submit=self.username_submit,
autofocus=True)
controls.extend([
ft.Row(
[self.username],
alignment=ft.MainAxisAlignment.CENTER,
),
])
self.password = ft.TextField(label="Password", width=200, password=True,
on_submit=self.password_submit,
autofocus=not self.show_username)
controls.extend([
ft.Row(
[self.password],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[
ft.FilledButton("Login", on_click=self.attempt_login),
ft.ElevatedButton("Clear", on_click=self.clear_login),
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(),
ft.Row(
[ft.Text("TODO: should have on-screen keyboard (at least 10-key pad?) "
"for use with login etc.", italic=True)],
alignment=ft.MainAxisAlignment.CENTER,
),
])
return [
self.build_header(),
ft.Column(controls=controls,
expand=True,
alignment=ft.MainAxisAlignment.CENTER),
]
def username_submit(self, e):
if self.username.value:
self.password.focus()
else:
self.username.focus()
def password_submit(self, e):
if self.password.value:
self.attempt_login()
else:
self.password.focus()
def clear_login(self, e):
if self.show_username:
self.username.value = ""
self.password.value = ""
if self.show_username:
self.username.focus()
else:
self.password.focus()
self.page.update()
def attempt_login(self, e=None):
if self.show_username and not self.username.value:
self.username.focus()
return
if not self.password.value:
self.password.focus()
return
session = self.app.make_session()
auth = self.app.get_auth_handler()
user = auth.authenticate_user(session, self.username.value, self.password.value)
user_display = str(user) if user else None
session.close()
if user:
# handle success
self.page.shared.update({
'user_uuid': user.uuid,
'user_display': user_display,
})
self.page.go('/pos')
else:
# handle failure
self.page.snack_bar = ft.SnackBar(ft.Text("Login failed!",
color='black',
weight=ft.FontWeight.BOLD),
bgcolor='yellow',
duration=1500)
self.page.snack_bar.open = True
self.password.focus()
self.page.update()

102
wuttapos/views/pos.py Normal file
View file

@ -0,0 +1,102 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - POS view
"""
import flet as ft
from .base import WuttaView
class POSView(WuttaView):
"""
Main POS view for WuttaPOS
"""
def build_controls(self):
self.main_input = ft.TextField(on_submit=self.main_submit,
autofocus=True)
def make_text(*args, **kwargs):
kwargs['weight'] = ft.FontWeight.BOLD
kwargs['size'] = 20
return ft.Text(*args, **kwargs)
return [
self.build_header(),
ft.Row(
[self.main_input],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(),
ft.Row(),
ft.Row(),
ft.Row(
[ft.Text("TODO: need lots of things yet here...somewhere..")],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[ft.Text("TODO: for instance, items rang up might go here")],
),
ft.DataTable(
columns=[
ft.DataColumn(make_text("UPC")),
ft.DataColumn(make_text("Description")),
ft.DataColumn(make_text("Price"), numeric=True),
],
rows=[
ft.DataRow(
cells=[
ft.DataCell(make_text("0007430500132-1")),
ft.DataCell(make_text("Apple Cider Vinegar 32oz")),
ft.DataCell(make_text("$5.99")),
],
),
ft.DataRow(
cells=[
ft.DataCell(make_text("0007430500116-1")),
ft.DataCell(make_text("Apple Cider Vinegar 16oz")),
ft.DataCell(make_text("$3.59")),
],
),
],
),
]
def main_submit(self, e):
value = self.main_input.value.upper()
self.page.snack_bar = ft.SnackBar(ft.Text(f"submit: {value}", color='black',
weight=ft.FontWeight.BOLD),
bgcolor='yellow',
duration=1500)
self.page.snack_bar.open = True
self.main_input.value = ""
self.main_input.focus()
self.page.update()