update shop

This commit is contained in:
2025-12-17 18:32:46 +02:00
parent d8c6de1f2b
commit 56f9da6966
9 changed files with 130 additions and 9 deletions

View File

@@ -22,10 +22,12 @@ RUN mkdir -p /app/instance /app/assets
# Default port
ENV FLET_PORT=8080
EXPOSE 8080
# Copy the entrypoint script and make it executable
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh
# Health check
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD curl -fsS http://127.0.0.1:8080/ || exit 1
# Expose both ports (Flet 8080 and Flask 9000)
EXPOSE 8080 9000
# Run entrypoint to create superuser and start the app
ENTRYPOINT ["sh", "-c", "python create_super_user.py && python main.py"]
# Use the script to start the container
ENTRYPOINT ["./entrypoint.sh"]

View File

@@ -38,6 +38,15 @@ class AdminChat:
on_click=self.on_send_click,
)
# Notification sound to be played on new client messages
# Make sure the file path points to a valid audio file in your assets.
# Example: place `chat_notify.mp3` in `assets/sounds/`.
self.notification_audio = ft.Audio(
src="assets/sounds/chat_notify_triple.mp3",
autoplay=True,
volume=1.0,
)
# Subscribe to PubSub for live updates from clients
try:
self.page.pubsub.subscribe(self.on_pubsub_message)
@@ -107,7 +116,19 @@ class AdminChat:
vertical_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.header_label,
ft.Icon(ft.Icons.SUPPORT_AGENT),
ft.Row(
[
ft.Icon(ft.Icons.SUPPORT_AGENT),
ft.WebView(
url="/enable-notifications", # small HTML page with a single 'Activează notificările' button
width=160,
height=40,
expand=False,
),
],
vertical_alignment=ft.CrossAxisAlignment.CENTER,
spacing=8,
),
],
),
ft.Divider(),
@@ -120,6 +141,7 @@ class AdminChat:
vertical_alignment=ft.CrossAxisAlignment.CENTER,
controls=[self.input_field, self.send_button],
),
self.notification_audio,
],
),
)
@@ -165,7 +187,7 @@ class AdminChat:
title = f"Chat #{chat_id}"
if user_id:
user = self.user_namager.get(user_id)
title += f" • User {user['name'].replace("~", " ")}"
title += f" • User {user['name'].replace('~', ' ')}"
subtitle_parts = []
if status == "open":
@@ -232,7 +254,7 @@ class AdminChat:
label = f"Chat #{chat_id}"
if user_id:
user = self.user_namager.get(user_id)
label += f" • User {user['name'].replace("~", " ")}"
label += f" • User {user['name'].replace('~', ' ')}"
self.header_label.value = label
else:
self.header_label.value = f"Chat #{chat_id}"
@@ -362,6 +384,14 @@ class AdminChat:
if data.get("type") == "chat_message" and data.get("sender") == "client":
chat_id = data.get("chat_id")
# Play notification sound for any incoming client message
try:
print('Play sound')
self.notification_audio.play()
print('Played sound')
except Exception as e:
print(e)
# If this is the currently open chat, append bubble directly
if self.active_chat_id == chat_id:
text = data.get("text", "")

Binary file not shown.

Binary file not shown.

14
UI_V2/chat/chat.py Normal file
View File

@@ -0,0 +1,14 @@
import flet as ft
class Chat:
def __init__(self, page: ft.Page):
self.page = page
def build(self):
return ft.Container(
content=ft.Column(
[
ft.Text("Aveti nevoie de ajutor?")
]
)
)

View File

@@ -25,6 +25,7 @@ services:
# SHOP_DB_PATH: "/app/instance/shop.db" # custom var
expose:
- "8080"
- "9000"
volumes:
- tg_instance:/app/instance
- tg_assets:/app/assets

12
UI_V2/entrypoint.sh Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
# 1. Run your superuser script
python create_super_user.py
# 2. Start Flask in the background (&)
# We use & to let it run while the script continues
python flask_server.py &
# 3. Start Flet (Main process)
# This stays in the foreground so the container doesn't exit
python main.py

62
UI_V2/flask_server.py Normal file
View File

@@ -0,0 +1,62 @@
from __future__ import annotations
import os
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask, request, jsonify
from flask_cors import CORS
try:
from dotenv import load_dotenv
load_dotenv()
except Exception:
pass
from UI_V2.helpers.netopia import verify_ipn, get_status
app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "*"}})
# ---------- Logging ----------
app.logger.setLevel(logging.INFO)
_log_dir = os.getenv("LOG_DIR", "logs")
os.makedirs(_log_dir, exist_ok=True)
_handler = RotatingFileHandler(os.path.join(_log_dir, "netopia_api.log"), maxBytes=1_000_000, backupCount=3)
_handler.setLevel(logging.INFO)
_handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(message)s"))
app.logger.addHandler(_handler)
@app.get("/healthz")
def healthz():
return {"ok": True}, 200
@app.post("/api/payments/ipn")
def ipn():
try:
raw = request.data
data = verify_ipn(raw)
app.logger.info("IPN OK: %s", data)
return jsonify({"ok": True, "data": data}), 200
except Exception as e:
app.logger.exception("IPN verification failed: %s", e)
return jsonify({"ok": False, "error": str(e)}), 400
@app.get("/api/payments/status")
def status():
ntp_id = request.args.get("ntpID")
order_id = request.args.get("orderID")
try:
resp = get_status(ntp_id=ntp_id, order_id=order_id)
return jsonify({"ok": True, "data": resp}), 200
except Exception as e:
app.logger.exception("Status query failed: %s", e)
return jsonify({"ok": False, "error": str(e)}), 400
if __name__ == "__main__":
host = os.getenv("API_HOST", "0.0.0.0")
port = int(os.getenv("API_PORT", "9000"))
app.logger.info("Starting NETOPIA Flask sidecar on %s:%s", host, port)
app.run(host=host, port=port)

View File

@@ -22,7 +22,7 @@ from dotenv import load_dotenv
load_dotenv()
def main(page: ft.Page):
page.title = "Taina Gustului"
page.title = "Taina Gustului - Condimente, nuci și fructe uscate în Craiova"
page.theme_mode = ft.ThemeMode.LIGHT
page.theme = ft.Theme(color_scheme=ft.ColorScheme(primary=ft.Colors.BROWN))
page.vertical_alignment = ft.MainAxisAlignment.CENTER