From 0f610a7901c65412d0e447087a14ff75c6b73550 Mon Sep 17 00:00:00 2001 From: Ualerson Date: Sat, 27 Sep 2025 17:30:14 -0300 Subject: [PATCH] landingpage e mais features --- .../Workflows => .github/workflows}/pr.yml | 10 +- Back-End/Models/postgreSQL.py | 39 +- Back-End/Modules/Resolvers/user_plan.py | 48 --- .../seed_invoices_for_freitas.md | 47 ++ Back-End/Workflows/PullRequest/pr.yml | 22 + Back-End/api.py | 403 ++++++++++++++---- Back-End/gen-prai.py | 36 ++ Back-End/requirements.txt | 13 +- Front-End/src/App.tsx | 14 +- Front-End/src/assets/hero-image.jpg | Bin 0 -> 127743 bytes Front-End/src/components/app-sidebar.tsx | 26 +- Front-End/src/components/cta-section.tsx | 88 ++++ Front-End/src/components/features-section.tsx | 138 ++++++ Front-End/src/components/footer.tsx | 92 ++++ Front-End/src/components/header.tsx | 98 +++++ Front-End/src/components/hero-section.tsx | 106 +++++ Front-End/src/components/pricing-section.tsx | 166 ++++++++ Front-End/src/constants/landingpage.ts | 50 +++ Front-End/src/pages/Billing.tsx | 242 +++++++++++ Front-End/src/pages/Index.tsx | 14 - Front-End/src/pages/Invoices.tsx | 255 +++++++++++ Front-End/src/pages/Landingpage.tsx | 23 + Front-End/src/pages/MyAccount.tsx | 150 +++++++ README.md | 4 +- build.py | 2 +- docker-compose.yml | 2 +- 26 files changed, 1924 insertions(+), 164 deletions(-) rename {Back-End/Workflows => .github/workflows}/pr.yml (58%) delete mode 100644 Back-End/Modules/Resolvers/user_plan.py create mode 100644 Back-End/TestDiscovery/seed_invoices_for_freitas.md create mode 100644 Back-End/Workflows/PullRequest/pr.yml create mode 100644 Back-End/gen-prai.py create mode 100644 Front-End/src/assets/hero-image.jpg create mode 100644 Front-End/src/components/cta-section.tsx create mode 100644 Front-End/src/components/features-section.tsx create mode 100644 Front-End/src/components/footer.tsx create mode 100644 Front-End/src/components/header.tsx create mode 100644 Front-End/src/components/hero-section.tsx create mode 100644 Front-End/src/components/pricing-section.tsx create mode 100644 Front-End/src/constants/landingpage.ts create mode 100644 Front-End/src/pages/Billing.tsx delete mode 100644 Front-End/src/pages/Index.tsx create mode 100644 Front-End/src/pages/Invoices.tsx create mode 100644 Front-End/src/pages/Landingpage.tsx create mode 100644 Front-End/src/pages/MyAccount.tsx diff --git a/Back-End/Workflows/pr.yml b/.github/workflows/pr.yml similarity index 58% rename from Back-End/Workflows/pr.yml rename to .github/workflows/pr.yml index 80dbfdea..c8b787f5 100644 --- a/Back-End/Workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -8,15 +8,15 @@ jobs: call-external-service: runs-on: ubuntu-latest steps: - - name: Chamar API para processar PR + - name: Chamar API PR AI run: | curl -X POST \ -H "Content-Type: application/json" \ - -H "X-API-TOKEN: ${{ secrets.GITHUB_TOKEN }}" \ + -H "X-API-TOKEN: ${{ secrets.PRAI_API_TOKEN }}" \ -d '{ "repository": "${{ github.repository }}", "pr_number": ${{ github.event.pull_request.number }}, - "pr_url": "${{ github.event.pull_request.url }}", - "diff_url": "${{ github.event.pull_request.diff_url }}" + "email": ${{ secrets.email }}, + "password": "${{ secrets.password }}", }' \ - https://b70c040bdbc5.ngrok-free.app/api/prai/gen + https://api.softwareai.site/api/prai/gen diff --git a/Back-End/Models/postgreSQL.py b/Back-End/Models/postgreSQL.py index 56229ed7..1f0f33ba 100644 --- a/Back-End/Models/postgreSQL.py +++ b/Back-End/Models/postgreSQL.py @@ -3,7 +3,8 @@ import bcrypt from datetime import datetime, timedelta import secrets - +import json +from sqlalchemy import Numeric TOKEN_DEFAULT_EXPIRES_DAYS = 30 @@ -96,3 +97,39 @@ class SystemSettings(db.Model): enable_logging = db.Column(db.Boolean, default=True) log_level = db.Column(db.String(50), default='INFO') updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + + +class Invoice(db.Model): + __tablename__ = 'invoices' + + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) + number = db.Column(db.String(64), nullable=False) # número/identificador da fatura + date = db.Column(db.DateTime, default=datetime.utcnow) + amount = db.Column(Numeric(12, 2), nullable=False, default=0.0) + currency = db.Column(db.String(8), default='BRL') + status = db.Column(db.String(32), default='pending') # paid, pending, failed + plan_name = db.Column(db.String(128), nullable=True) + pdf_path = db.Column(db.String(500), nullable=True) # path relativo em ./invoices/ ou None + pdf_url = db.Column(db.String(1000), nullable=True) # opcional: url externa se armazenada em S3 etc. + lines = db.Column(db.Text, nullable=True) # JSON serializado com itens [{description, qty, price}, ...] + created_at = db.Column(db.DateTime, default=datetime.utcnow) + updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + + def to_dict(self, include_lines=False): + data = { + "id": str(self.id), + "number": self.number, + "date": self.date.isoformat() if self.date else None, + "amount": float(self.amount) if self.amount is not None else 0.0, + "currency": self.currency, + "status": self.status, + "planName": self.plan_name, + "pdfUrl": self.pdf_url or (f"/api/invoices/{self.id}/download" if self.pdf_path else None) + } + if include_lines: + try: + data["lines"] = json.loads(self.lines) if self.lines else [] + except Exception: + data["lines"] = [] + return data diff --git a/Back-End/Modules/Resolvers/user_plan.py b/Back-End/Modules/Resolvers/user_plan.py deleted file mode 100644 index effe4c6f..00000000 --- a/Back-End/Modules/Resolvers/user_plan.py +++ /dev/null @@ -1,48 +0,0 @@ - -from Modules.Resolvers.user_identifier import auth_user, require_user_token, resolve_user_identifier - -def user_plan_limit(email, password, logs_collection, app): - - user, _, status = auth_user(email, password, logs_collection, app) - - if status != "success" or not user: - return False - - numeric_user_id = user.id - plan_name = user.plan_name - if plan_name == "Free": - payload = { - 'price': 0, - 'limit_monthly_tokens': 300000, - 'features': [ - 'PR basic automation', - '5 - 10 PRs/mo', - 'Logs basic' - ] - } - elif plan_name == "Premium": - payload = { - 'price': 15, - 'limit_monthly_tokens': 3000000, - 'features': [ - 'PR Premium automation', - '20 - 40 PRs/mo', - 'Logs advanced', - 'API access' - ] - } - - elif plan_name == "Pro": - payload = { - 'price': 29, - 'limit_monthly_tokens': 10000000, - 'features': [ - 'Everything from Premium', - '60 - 90 PRs/mo', - 'Git Context Layer', - 'Auto-Commit Intelligence', - 'Smart Threshold Detection', - 'Context-Aware Messages' - ] - } - return payload \ No newline at end of file diff --git a/Back-End/TestDiscovery/seed_invoices_for_freitas.md b/Back-End/TestDiscovery/seed_invoices_for_freitas.md new file mode 100644 index 00000000..e03361cc --- /dev/null +++ b/Back-End/TestDiscovery/seed_invoices_for_freitas.md @@ -0,0 +1,47 @@ +docker exec -i meu_postgres2 psql -U postgres -d meubanco <<'SQL' +-- seed_invoices_for_freitas.sql +BEGIN; + +-- 1) garante que o usuário exista (insere se não existir) e retorna id em CTE +WITH upsert_user AS ( + INSERT INTO users (email, username, password_hash, created_at, plan_name, limit_monthly_tokens, tokens_used, acess_token, expires_at) + VALUES ( + 'freitasalexandre815@gmail.com', + 'freitasalexandre', + '', + NOW(), + 'Pro', + 1000000, + 1234, + 'testtoken-inv-5000', + NOW() + INTERVAL '30 days' + ) + ON CONFLICT (email) DO UPDATE + SET username = EXCLUDED.username + RETURNING id +), uid AS ( + SELECT id FROM upsert_user + UNION ALL + SELECT id FROM users WHERE email = 'freitasalexandre815@gmail.com' LIMIT 1 +) + +-- 2) Insere 3 faturas somente se não existirem com o mesmo número para esse usuário +INSERT INTO invoices (user_id, number, date, amount, currency, status, plan_name, pdf_path, pdf_url, lines, created_at, updated_at) +SELECT uid.id, v.number, v.date, v.amount, v.currency, v.status, v.plan_name, v.pdf_path, v.pdf_url, v.lines, v.created_at, v.updated_at +FROM uid +CROSS JOIN ( + VALUES + ('INV-2025-0001', NOW() - INTERVAL '10 days', 49.90, 'BRL', 'paid', 'Pro', 'invoice-2025-0001.pdf', NULL, '[{"description":"Assinatura mensal Pro","qty":1,"price":49.90}]', NOW() - INTERVAL '10 days', NOW() - INTERVAL '10 days'), + ('INV-2025-0002', NOW() - INTERVAL '5 days', 49.90, 'BRL', 'pending', 'Pro', NULL, NULL, '[{"description":"Renovação pendente - Pro","qty":1,"price":49.90}]', NOW() - INTERVAL '5 days', NOW() - INTERVAL '5 days'), + ('INV-2025-0003', NOW() - INTERVAL '30 days', 249.00, 'BRL', 'paid', 'Business', NULL, 'https://example-bucket.s3.amazonaws.com/invoice-2025-0003.pdf', '[{"description":"Assinatura anual Business","qty":1,"price":249.00}]', NOW() - INTERVAL '30 days', NOW() - INTERVAL '30 days') +) AS v(number, date, amount, currency, status, plan_name, pdf_path, pdf_url, lines, created_at, updated_at) +WHERE NOT EXISTS ( + SELECT 1 FROM invoices i WHERE i.number = v.number AND i.user_id = uid.id +); + +-- 3) Ajusta sequences +SELECT setval(pg_get_serial_sequence('users','id'), (SELECT COALESCE(MAX(id),1) FROM users)); +SELECT setval(pg_get_serial_sequence('invoices','id'), (SELECT COALESCE(MAX(id),1) FROM invoices)); + +COMMIT; +SQL diff --git a/Back-End/Workflows/PullRequest/pr.yml b/Back-End/Workflows/PullRequest/pr.yml new file mode 100644 index 00000000..c8b787f5 --- /dev/null +++ b/Back-End/Workflows/PullRequest/pr.yml @@ -0,0 +1,22 @@ +name: Processar Pull Request + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + call-external-service: + runs-on: ubuntu-latest + steps: + - name: Chamar API PR AI + run: | + curl -X POST \ + -H "Content-Type: application/json" \ + -H "X-API-TOKEN: ${{ secrets.PRAI_API_TOKEN }}" \ + -d '{ + "repository": "${{ github.repository }}", + "pr_number": ${{ github.event.pull_request.number }}, + "email": ${{ secrets.email }}, + "password": "${{ secrets.password }}", + }' \ + https://api.softwareai.site/api/prai/gen diff --git a/Back-End/api.py b/Back-End/api.py index 14b5f679..5cca2b98 100644 --- a/Back-End/api.py +++ b/Back-End/api.py @@ -4,6 +4,8 @@ import requests import json import logging +from dotenv import load_dotenv + from bson.json_util import dumps from datetime import datetime, timedelta, timezone @@ -11,13 +13,15 @@ from flask_cors import CORS from asgiref.wsgi import WsgiToAsgi from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity -from dotenv import load_dotenv +from flask_limiter import Limiter +from flask_limiter.util import get_remote_address from Models.postgreSQL import * from Modules.Resolvers.pr_process import process_pull_request from Modules.Resolvers.user_identifier import auth_user, require_user_token, resolve_user_identifier from Modules.Geters.systemsettings import * + from Models.mongoDB import ( Log, AuditTrail, @@ -36,6 +40,10 @@ load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), 'keys.env')) +INVOICES_DIR = os.path.join(os.path.dirname(__file__), 'invoices') +os.makedirs(INVOICES_DIR, exist_ok=True) + + app = Flask(__name__) asgi_app = WsgiToAsgi(app) @@ -51,11 +59,17 @@ app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False jwt = JWTManager(app) -# CORS(app, resources={ -# r"/api/*": { -# "origins": os.getenv('FRONTEND_ORIGINS', '*').split(',') -# } -# }) +limiter = Limiter( + get_remote_address, + app=app, + default_limits=[] +) + +CORS(app, resources={ + r"/api/*": { + "origins": os.getenv('FRONTEND_ORIGINS', '*').split(',') + } +}) db.init_app(app) @app.route('/') @@ -66,7 +80,66 @@ def index(): "database": "PostgreSQL + MongoDB", "status": "running" }) + +def get_plans_data(): + return { + "Free": { + 'price': 0, + 'limit_monthly_tokens': 300000, + 'features': [ + 'PR basic automation', + '5 - 10 PRs/mo', + 'Logs basic' + ] + }, + "Premium": { + 'price': 15, + 'limit_monthly_tokens': 3000000, + 'features': [ + 'PR Premium automation', + '20 - 40 PRs/mo', + 'Logs advanced', + 'API access' + ] + }, + "Pro": { + 'price': 29, + 'limit_monthly_tokens': 10000000, + 'features': [ + 'Everything from Premium', + '60 - 90 PRs/mo', + 'Git Context Layer', + 'Auto-Commit Intelligence', + 'Smart Threshold Detection', + 'Context-Aware Messages' + ] + } + } +@app.route('/api/public/plans-features', methods=['GET']) +@limiter.limit("5 per minute") +def public_plans_features(): + return jsonify({ + "message": "Lista pública de planos e features", + "payload": get_plans_data() + }), 200 + + +@app.route('/api/plans-features//', methods=['GET']) +def user_plan_limit(email, password): + user, _, status = auth_user(email, password, logs_collection, app) + if status != "success" or not user: + return jsonify({"error": "Credenciais inválidas"}), 401 + plans = get_plans_data() + plan_name = user.plan_name + + if plan_name not in plans: + return jsonify({"error": "Plano não encontrado"}), 404 + + return jsonify({ + "message": "Plano do usuário", + "payload": plans[plan_name], + }), 200 @app.route('/api/register', methods=['POST']) def register(): @@ -104,7 +177,7 @@ def register(): @app.route('/api/login', methods=['POST']) @require_user_token(optional=True) def login(): - data = request.get_json() or {} + data = request.get_json() email = data.get("email") password = data.get("password") try: @@ -123,7 +196,7 @@ def login(): log_action(logs_collection, 'login_success', {'username': email}, user=user.id) return jsonify({ "message": f"Bem-vindo, {user.email}!", - "access_token": access_token_to_return, + "access_token": user.acess_token, "user_id": user.id, "plan_name": user.plan_name, "limit_monthly_tokens": user.limit_monthly_tokens, @@ -781,6 +854,7 @@ def get_pull_request_details(pr_id): 'author': author, 'aiGeneratedContent': ai_generated_content, 'originalDiff': original_diff, + 'total_tokens': pr.total_tokens, 'errorMessage': None if pr.status != 'error' else f'Error processing PR #{pr.pr_number}' } @@ -976,78 +1050,6 @@ def get_dashboard_data(): return jsonify({'error': 'Failed to fetch dashboard data'}), 500 -@app.route('/api/reprocess-pr/', methods=['POST']) -@require_user_token(optional=False) -def reprocess_pr(pr_number): - """Reprocessar um Pull Request específico""" - data = request.get_json() - user_email = data.get("email") - user_senha = data.get("password") - redo_merge = data.get("redo_merge") - - user, _, status = auth_user(user_email, user_senha, logs_collection, app) - - if status != "success" or not user: - return jsonify({"error": "Usuário não autenticado ou inválido"}), 401 - - numeric_user_id = user.id - - model = "gpt-5-nano" - GITHUB_TOKEN, OPENAI_API_KEY, GITHUB_SECRET, REPOSITORY_NAME = get_tokens(numeric_user_id, log_action, logs_collection, SystemSettings, db) - thread = threading.Thread(target=process_pull_request, args=( - app, - numeric_user_id, - GITHUB_TOKEN, - OPENAI_API_KEY, - logs_collection, - pr_number, - REPOSITORY_NAME, - model, - redo_merge, - )) - thread.daemon = True - thread.start() - - return jsonify({ - 'message': 'Processing started', - 'pr_number': pr_number, - 'triggered_by': numeric_user_id - }), 202 - -@app.route('/api/prai/gen', methods=['POST']) -def prai(): - model = "gpt-5-nano" - payload = request.get_json() - user_id = request.args.get("user_id") or (request.get_json(silent=True) or {}).get("user_id") - if not user_id: - return jsonify({"error": "user_id obrigatório"}), 400 - - GitToken = request.headers.get('Bearer') - if not GitToken: - return jsonify({"error": "GitToken obrigatório"}), 400 - - user = resolve_user_identifier(user_id) - if not user: - return jsonify({"error": "Usuário não encontrado."}), 404 - - numeric_user_id = user.id - GITHUB_TOKEN, OPENAI_API_KEY, GITHUB_SECRET, REPOSITORY_NAME = get_tokens(numeric_user_id, log_action, logs_collection, SystemSettings, db) - repository = payload["repository"] - pr_number = payload["pr_number"] - threading.Thread(target=process_pull_request, args=( - app, - numeric_user_id, - GitToken, - OPENAI_API_KEY, - logs_collection, - pr_number, - repository, - model, - )).start() - return 'Processamento do Pull Request iniciado', 202 - - - @app.route('/api/workflows', methods=['GET']) @require_user_token(optional=False) def list_workflows(): @@ -1056,7 +1058,6 @@ def list_workflows(): Retorna JSON: { "workflows": [ { id, name, category, createdAt, yaml, git }, ... ] } """ try: - # obter credenciais do query params ou body (compatível com frontend) user_email = request.args.get("email") or (request.json and request.json.get("email")) user_senha = request.args.get("password") or (request.json and request.json.get("password")) @@ -1066,8 +1067,9 @@ def list_workflows(): numeric_user_id = user.id - # diretório de workflows — configurável via env - workflows_dir = os.getenv('WORKFLOWS_PATH', os.path.join(os.path.dirname(__file__), 'workflows')) + # diretório de workflows + workflows_dir = os.path.join(os.path.dirname(__file__), 'Workflows') + workflows = [] @@ -1106,6 +1108,241 @@ def list_workflows(): log_action(logs_collection, 'workflows_list_error', {'error': str(e)}, user=(getattr(g, 'current_user', None) or None), level='error') return jsonify({'error': 'Failed to list workflows', 'detail': str(e)}), 500 +@app.route('/api/myaccount', methods=['GET']) +@require_user_token(optional=False) +def my_account(): + """ + Retorna informações da conta do usuário autenticado. + Inclui plano, limites e status de expiração. + """ + try: + user_email = request.args.get("email") or (request.json and request.json.get("email")) + user_senha = request.args.get("password") or (request.json and request.json.get("password")) + + user, _, status = auth_user(user_email, user_senha, logs_collection, app) + if status != "success" or not user: + return jsonify({"error": "Usuário não autenticado ou inválido"}), 401 + + numeric_user_id = user.id + response = { + "user_id": user.id, + "email": user.email, + "planName": user.plan_name, + "planExpiresAt": user.expires_at.isoformat() if user.expires_at else None, + "tokensUsed": user.tokens_used or 0, + "tokenLimit": user.limit_monthly_tokens or 0, + "remainingTokens": (user.limit_monthly_tokens or 0) - (user.tokens_used or 0), + "accessToken": user.acess_token, + "createdAt": user.created_at.isoformat() if user.created_at else None, + } + + log_action(logs_collection, 'myaccount_accessed', response, user=user.id) + return jsonify(response), 200 + + except Exception as e: + log_action(logs_collection, 'myaccount_error', {'error': str(e)}, level='error') + return jsonify({"error": "Erro ao recuperar informações da conta", "detail": str(e)}), 500 + + +@app.route('/api/invoices', methods=['GET']) +@require_user_token(optional=False) +def list_invoices(): + """ + Listar faturas paginadas. + Query params: page, limit, status, q, email, password (compatibilidade com auth_user) + Retorna: { invoices: [...], total: N } + """ + try: + page = int(request.args.get('page', 1)) + limit = int(request.args.get('limit', 12)) + status = request.args.get('status') + q = request.args.get('q', '').strip() + + # autentica (compatível com existing pattern) + user_email = request.args.get("email") or (request.json and request.json.get("email")) + user_senha = request.args.get("password") or (request.json and request.json.get("password")) + user, _, status_auth = auth_user(user_email, user_senha, logs_collection, app) + + if status_auth != "success" or not user: + return jsonify({"error": "Usuário não autenticado ou inválido"}), 401 + + numeric_user_id = user.id + + query = Invoice.query.filter_by(user_id=numeric_user_id) + + if status: + query = query.filter(Invoice.status == status) + + if q: + like = f"%{q}%" + query = query.filter(db.or_(Invoice.number.ilike(like), Invoice.plan_name.ilike(like))) + + total = query.count() + + invoices_page = query.order_by(Invoice.date.desc()).offset((page - 1) * limit).limit(limit).all() + + invoices_data = [inv.to_dict(include_lines=False) for inv in invoices_page] + + log_action(logs_collection, 'invoices_listed', {'count': len(invoices_data), 'page': page}, user=numeric_user_id) + return jsonify({"invoices": invoices_data, "total": total}) + except Exception as e: + log_action(logs_collection, 'invoices_list_error', {'error': str(e)}, user=(getattr(g, 'current_user', None) or None), level='error') + return jsonify({'error': 'Failed to list invoices', 'detail': str(e)}), 500 + + +@app.route('/api/invoices/', methods=['GET']) +@require_user_token(optional=False) +def get_invoice_detail(invoice_id): + """ + Detalhe da fatura (inclui linhas / itens). + """ + try: + user_email = request.args.get("email") or (request.json and request.json.get("email")) + user_senha = request.args.get("password") or (request.json and request.json.get("password")) + user, _, status_auth = auth_user(user_email, user_senha, logs_collection, app) + + if status_auth != "success" or not user: + return jsonify({"error": "Usuário não autenticado ou inválido"}), 401 + + numeric_user_id = user.id + + inv = Invoice.query.filter_by(id=invoice_id, user_id=numeric_user_id).first() + if not inv: + return jsonify({'error': 'Invoice not found'}), 404 + + inv_data = inv.to_dict(include_lines=True) + + log_action(logs_collection, 'invoice_detail_accessed', {'invoice_id': invoice_id}, user=numeric_user_id) + return jsonify(inv_data) + except Exception as e: + log_action(logs_collection, 'invoice_detail_error', {'error': str(e), 'invoice_id': invoice_id}, user=(getattr(g, 'current_user', None) or None), level='error') + return jsonify({'error': 'Failed to fetch invoice detail', 'detail': str(e)}), 500 + + +@app.route('/api/invoices//download', methods=['GET']) +@require_user_token(optional=False) +def download_invoice(invoice_id): + """ + Download do PDF da fatura. + Se Invoice.pdf_url estiver setado como URL externa, redireciona para ela. + Se Invoice.pdf_path estiver configurado, serve o arquivo do diretório INVOICES_DIR. + """ + try: + user_email = request.args.get("email") or (request.json and request.json.get("email")) + user_senha = request.args.get("password") or (request.json and request.json.get("password")) + user, _, status_auth = auth_user(user_email, user_senha, logs_collection, app) + + if status_auth != "success" or not user: + return jsonify({"error": "Usuário não autenticado ou inválido"}), 401 + + numeric_user_id = user.id + + inv = Invoice.query.filter_by(id=invoice_id, user_id=numeric_user_id).first() + if not inv: + return jsonify({'error': 'Invoice not found'}), 404 + + # Prioriza URL externa + if inv.pdf_url: + log_action(logs_collection, 'invoice_download_redirect', {'invoice_id': invoice_id, 'url': inv.pdf_url}, user=numeric_user_id) + return jsonify({'pdfUrl': inv.pdf_url}), 200 + + # Se tiver path relativo, tenta servir o arquivo + if inv.pdf_path: + # garante que não escape o diretório + file_path = os.path.join(INVOICES_DIR, inv.pdf_path) + if not os.path.exists(file_path): + log_action(logs_collection, 'invoice_download_missing_file', {'invoice_id': invoice_id, 'path': file_path}, user=numeric_user_id, level='warning') + return jsonify({'error': 'Arquivo de fatura não encontrado no servidor'}), 404 + + # usa send_file com attachment_filename (flask >=2) + try: + log_action(logs_collection, 'invoice_download_served', {'invoice_id': invoice_id, 'file': inv.pdf_path}, user=numeric_user_id) + return send_file(file_path, mimetype='application/pdf', as_attachment=True, download_name=f"invoice-{inv.number}.pdf") + except Exception as e: + log_action(logs_collection, 'invoice_download_error', {'invoice_id': invoice_id, 'error': str(e)}, user=numeric_user_id, level='error') + return jsonify({'error': 'Erro ao servir arquivo de fatura', 'detail': str(e)}), 500 + + # nenhum arquivo nem url configurado + return jsonify({'error': 'Nenhum arquivo de fatura disponível'}), 404 + + except Exception as e: + log_action(logs_collection, 'invoice_download_exception', {'error': str(e), 'invoice_id': invoice_id}, user=(getattr(g, 'current_user', None) or None), level='error') + return jsonify({'error': 'Failed to download invoice', 'detail': str(e)}), 500 + + + +@app.route('/api/reprocess-pr/', methods=['POST']) +@require_user_token(optional=False) +def reprocess_pr(pr_number): + """Reprocessar um Pull Request específico""" + data = request.get_json() + user_email = data.get("email") + user_senha = data.get("password") + redo_merge = data.get("redo_merge") + + user, _, status = auth_user(user_email, user_senha, logs_collection, app) + + if status != "success" or not user: + return jsonify({"error": "Usuário não autenticado ou inválido"}), 401 + + numeric_user_id = user.id + + model = "gpt-5-nano" + GITHUB_TOKEN, OPENAI_API_KEY, GITHUB_SECRET, REPOSITORY_NAME = get_tokens(numeric_user_id, log_action, logs_collection, SystemSettings, db) + thread = threading.Thread(target=process_pull_request, args=( + app, + numeric_user_id, + GITHUB_TOKEN, + OPENAI_API_KEY, + logs_collection, + pr_number, + REPOSITORY_NAME, + model, + redo_merge, + )) + thread.daemon = True + thread.start() + + return jsonify({ + 'message': 'Processing started', + 'pr_number': pr_number, + 'triggered_by': numeric_user_id + }), 202 + +@app.route('/api/prai/gen', methods=['POST']) +@require_user_token(optional=False) +def prai(): + data = request.get_json() + user_email = data.get("email") + user_senha = data.get("password") + repository = data.get("repository") + pr_number = data.get("pr_number") + + user, _, status = auth_user(user_email, user_senha, logs_collection, app) + + if status != "success" or not user: + return jsonify({"error": "Usuário não autenticado ou inválido"}), 401 + + numeric_user_id = user.id + model = "gpt-5-nano" + GITHUB_TOKEN, OPENAI_API_KEY, GITHUB_SECRET, REPOSITORY_NAME = get_tokens(numeric_user_id, log_action, logs_collection, SystemSettings, db) + + threading.Thread(target=process_pull_request, args=( + app, + numeric_user_id, + GITHUB_TOKEN, + OPENAI_API_KEY, + logs_collection, + pr_number, + repository, + model, + )).start() + + return jsonify({ + 'message': 'Processing started', + 'pr_number': pr_number, + 'triggered_by': numeric_user_id + }), 202 # Endpoints nao desenvolvidos e Pendentes diff --git a/Back-End/gen-prai.py b/Back-End/gen-prai.py new file mode 100644 index 00000000..c57773e3 --- /dev/null +++ b/Back-End/gen-prai.py @@ -0,0 +1,36 @@ +import requests +import os +from dotenv import load_dotenv +load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), 'Keys', 'keys.env')) + + +API_URL = "http://localhost:5920/api/prai/gen" + +API_TOKEN = "WBYZIJ3-HCxGandUwpa96l_XlEf1TbYY2oY-4mtL-Hw" +REPOSITORY = "ualers2/SoftwareAI" +PR_NUMBER = 92 +EMAIL = "freitasalexandre815@gmail.com" +PASSWORD = "teste" + +payload = { + "repository": REPOSITORY, + "pr_number": PR_NUMBER, + "email": EMAIL, + "password": PASSWORD, +} + +headers = { + "Content-Type": "application/json", + "X-API-TOKEN": API_TOKEN, +} + +def testar_endpoint(): + try: + response = requests.post(API_URL, json=payload, headers=headers, timeout=30) + print("Status Code:", response.status_code) + print("Resposta JSON:", response.json()) + except Exception as e: + print("Erro ao chamar o endpoint:", str(e)) + +if __name__ == "__main__": + testar_endpoint() diff --git a/Back-End/requirements.txt b/Back-End/requirements.txt index 95cb3e08..9b88a110 100644 --- a/Back-End/requirements.txt +++ b/Back-End/requirements.txt @@ -1,18 +1,23 @@ Flask +flask-limiter +Flask-CORS==4.0.0 +Flask-JWT-Extended==4.6.0 +Flask-SQLAlchemy==3.1.1 +sqlalchemy==2.0.25 + python-dotenv openai-agents asyncio uvicorn asgiref -Flask-CORS==4.0.0 -Flask-JWT-Extended==4.6.0 + psycopg2-binary==2.9.9 pymongo==4.6.1 python-dotenv==1.0.0 requests==2.31.0 bcrypt==4.1.2 -sqlalchemy==2.0.25 -Flask-SQLAlchemy==3.1.1 + + tiktoken diff --git a/Front-End/src/App.tsx b/Front-End/src/App.tsx index 9ca95297..a5a21647 100644 --- a/Front-End/src/App.tsx +++ b/Front-End/src/App.tsx @@ -12,7 +12,11 @@ import Controls from "./pages/Controls"; import Settings from "./pages/Settings"; import NotFound from "./pages/NotFound"; import Login from "./pages/Login"; -import Workflows from "./pages/Workflows"; +import Workflows from "./pages/Workflows"; +import MyAccount from "./pages/MyAccount"; +import BillingPage from "./pages/Billing"; +import InvoicesPage from "./pages/Invoices"; +import Index from "./pages/Landingpage"; import { AuthProvider, useAuth } from "./contexts/AuthContext"; import ProtectedRoute from "./components/ProtectedRoute"; @@ -33,12 +37,18 @@ const AppRoutes = () => { } /> } /> } /> + } /> + } /> + } /> + } /> ) : ( - + + } /> + } /> } /> diff --git a/Front-End/src/assets/hero-image.jpg b/Front-End/src/assets/hero-image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..10bef923e76ed7f2141e4d8bb531e87c488a7e90 GIT binary patch literal 127743 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 { + const { links, cta } = project[0]; + + return ( +

+ {/* Background Elements */} +
+ ); +}; diff --git a/Front-End/src/components/features-section.tsx b/Front-End/src/components/features-section.tsx new file mode 100644 index 00000000..52db8f76 --- /dev/null +++ b/Front-End/src/components/features-section.tsx @@ -0,0 +1,138 @@ +import { + Bot, + Clock, + FileText, + GitBranch, + LineChart, + Shield, + Webhook, + Zap +} from "lucide-react"; + +export const FeaturesSection = () => { + const features = [ + { + icon: Bot, + title: "IA Avançada", + description: "Powered by GPT-5 otimizado para análise de código e geração de documentação técnica precisa.", + gradient: "from-purple-500 to-blue-500" + }, + { + icon: Clock, + title: "90% Economia de Tempo", + description: "Automatize completamente a criação de descrições de PRs. Foque no que realmente importa: o código.", + gradient: "from-green-500 to-teal-500" + }, + { + icon: GitBranch, + title: "Integração GitHub", + description: "Setup em 2 minutos via webhook. Funciona automaticamente com qualquer repositório público ou privado.", + gradient: "from-orange-500 to-red-500" + }, + { + icon: FileText, + title: "Templates Inteligentes", + description: "Descrições estruturadas seguindo as melhores práticas de documentação de engenharia de software.", + gradient: "from-blue-500 to-indigo-500" + }, + { + icon: LineChart, + title: "Analytics & Insights", + description: "Dashboard completo com métricas de produtividade, qualidade de código e performance da equipe.", + gradient: "from-pink-500 to-purple-500" + }, + { + icon: Shield, + title: "Segurança Enterprise", + description: "JWT authentication, logs de auditoria completos e conformidade com padrões de segurança.", + gradient: "from-cyan-500 to-blue-500" + }, + { + icon: Webhook, + title: "Webhooks Customizados", + description: "Integre com Slack, Discord, Teams ou qualquer ferramenta via webhooks personalizáveis.", + gradient: "from-yellow-500 to-orange-500" + }, + { + icon: Zap, + title: "Processamento Instantâneo", + description: "Chunking inteligente para PRs de qualquer tamanho. Processamento em segundos, não minutos.", + gradient: "from-emerald-500 to-green-500" + } + ]; + + return ( +
+ {/* Background Elements */} +
+
+
+
+ +
+ {/* Header */} +
+

+ Recursos que Aceleram +
+ sua Produtividade +

+

+ PR-AI não é apenas outro bot. É a primeira equipe de IA verdadeiramente funcional, + projetada para integrar perfeitamente ao seu workflow existente. +

+
+ + {/* Features Grid */} +
+ {features.map((feature, index) => ( +
+ {/* Icon */} +
+ +
+ + {/* Content */} +

+ {feature.title} +

+

+ {feature.description} +

+
+ ))} +
+ + {/* Stats Section */} +
+
+
+
90%
+
Menos Tempo
+
na documentação
+
+
+
2min
+
Setup
+
integração completa
+
+
+
24/7
+
Automação
+
sem intervenção
+
+
+
100%
+
Consistência
+
na documentação
+
+
+
+
+
+ ); +}; \ No newline at end of file diff --git a/Front-End/src/components/footer.tsx b/Front-End/src/components/footer.tsx new file mode 100644 index 00000000..4b12be64 --- /dev/null +++ b/Front-End/src/components/footer.tsx @@ -0,0 +1,92 @@ +import { Github, Mail, ExternalLink } from "lucide-react"; +import { project } from "@/constants/landingpage.ts"; + +export const Footer = () => { + const github = project[0].links.github + const email = project[0].links.email + + return ( + + ); +}; \ No newline at end of file diff --git a/Front-End/src/components/header.tsx b/Front-End/src/components/header.tsx new file mode 100644 index 00000000..d84127be --- /dev/null +++ b/Front-End/src/components/header.tsx @@ -0,0 +1,98 @@ +import { useState } from "react"; +import { Menu, X, Github } from "lucide-react"; +import { project } from "@/constants/landingpage.ts"; + +export const Header = () => { + const [isMenuOpen, setIsMenuOpen] = useState(false); + const { header, links } = project[0]; + + return ( +
+
+
+ {/* Logo */} +
+
+ AI +
+
+

PR-AI

+

by SoftwareAI

+
+
+ + {/* Desktop Navigation */} + + + {/* Desktop Actions */} + + + {/* Mobile Menu Button */} + +
+ + {/* Mobile Menu */} + {isMenuOpen && ( + + )} +
+
+ ); +}; diff --git a/Front-End/src/components/hero-section.tsx b/Front-End/src/components/hero-section.tsx new file mode 100644 index 00000000..13425085 --- /dev/null +++ b/Front-End/src/components/hero-section.tsx @@ -0,0 +1,106 @@ +import { ArrowRight, Github, Zap } from "lucide-react"; +import heroImage from "@/assets/hero-image.jpg"; +import { project } from "@/constants/landingpage.ts"; + +export const HeroSection = () => { + const { github, app } = project[0].links; + + + + return ( +
+ {/* Background Image with Overlay */} +
+ PR-AI Hero Background +
+
+ + {/* Floating Elements */} +
+
+
+
+
+ + {/* Main Content */} +
+
+ {/* Badge */} +
+ + Primeiro Protótipo Funcional +
+ + {/* Main Heading */} +

+ PR-AI +
+ Automatize sua +
+ Documentação +

+ + {/* Subtitle */} +

+ A primeira equipe de IA funcional do SoftwareAI. + Gere descrições de Pull Requests profissionais automaticamente e economize 90% do seu tempo. +

+ + {/* CTA Buttons */} + + + {/* Trust Indicators */} +
+
+
+ +
+
+
90% Economia
+
de tempo na documentação
+
+
+
+
+ +
+
+
GitHub Integration
+
Webhook automático
+
+
+
+
+ +
+
+
IA Avançada
+
GPT-5 otimizado
+
+
+
+
+
+ + {/* Scroll Indicator */} +
+
+
+
+
+
+ ); +}; \ No newline at end of file diff --git a/Front-End/src/components/pricing-section.tsx b/Front-End/src/components/pricing-section.tsx new file mode 100644 index 00000000..9bc1a397 --- /dev/null +++ b/Front-End/src/components/pricing-section.tsx @@ -0,0 +1,166 @@ +import { Check, Star, Zap } from "lucide-react"; +import { useEffect, useState } from "react"; +import { project } from "@/constants/landingpage.ts"; + +export const PricingSection = () => { + const [isAnnual, setIsAnnual] = useState(false); + + const backend = import.meta.env.VITE_BACK_END || '' + const [plans, setPlans] = useState([]); + + useEffect(() => { + fetch(`${backend}/api/public/plans-features`) + .then((res) => res.json()) + .then((data) => { + if (data.payload) { + // transforma objeto em array para mapear + const formattedPlans = Object.entries(data.payload).map(([name, info]: any) => ({ + name, + description: `Plano ${name} para diferentes necessidades`, + monthlyPrice: info.price, + annualPrice: Math.round(info.price * 0.83), // desconto ~17% + features: info.features, + isPopular: name === "Premium", // destaque no frontend + })); + setPlans(formattedPlans); + } + }) + .catch((err) => console.error("Erro ao buscar planos:", err)); + }, []); + + return ( +
+
+ {/* Header */} +
+

+ Planos que Escalam +
+ com seu Crescimento +

+

+ Escolha o plano perfeito para sua equipe. Todos os planos incluem 7 dias grátis para testar. +

+ + {/* Toggle Annual/Monthly */} +
+ + Mensal + + + + Anual + + {isAnnual && ( + + -17% Desconto + + )} +
+
+ + {/* Pricing Cards */} +
+ {plans.map((plan, index) => ( +
+ {plan.isPopular && ( +
+
+ + Mais Popular +
+
+ )} + + {/* Plan Header */} +
+

{plan.name}

+

{plan.description}

+
+ + ${isAnnual ? plan.annualPrice : plan.monthlyPrice} + + /mês +
+ {isAnnual && ( +
+ Faturado anualmente (${(isAnnual ? plan.annualPrice : plan.monthlyPrice) * 12}) +
+ )} +
+ + {/* Features */} +
+ {plan.features.map((feature, featureIndex) => ( +
+
+ +
+ {feature} +
+ ))} +
+ + {/* CTA Button */} + + + + {plan.isPopular && ( +
+ + ⚡ Setup em menos de 5 minutos + +
+ )} +
+ ))} +
+ + {/* Enterprise CTA */} +
+
+

+ Precisa de algo Personalizado? +

+

+ Para organizações com necessidades específicas, oferecemos planos enterprise + totalmente customizados com recursos avançados e suporte dedicado. +

+ +
+
+
+
+ ); +}; \ No newline at end of file diff --git a/Front-End/src/constants/landingpage.ts b/Front-End/src/constants/landingpage.ts new file mode 100644 index 00000000..e01cc2cc --- /dev/null +++ b/Front-End/src/constants/landingpage.ts @@ -0,0 +1,50 @@ +export const project = [ +{ + id: 1, + links: { + github: 'https://github.com/ualers2/SoftwareAI', + app: 'https://www.softwareai.site/login', + email: '' + }, + cta: { + title: "Pronto para Revolucionar seu Workflow?", + description: + "Junte-se a centenas de equipes que já economizam horas semanais com PR-AI. Setup em 2 minutos, resultados imediatos.", + benefits: [ + "7 dias grátis", + "Sem cartão de crédito", + "Cancelamento fácil", + "Suporte brasileiro", + ], + socialProofTitle: "Confiado por desenvolvedores em empresas como:", + companies: ["Media Cuts Studio", "Employers AI", "Docshepere", "CodeLab"], + }, + header: { + navigation: [ + { name: "Recursos", href: "#features" }, + { name: "Preços", href: "#pricing" }, + { name: "Documentação", href: "#docs" }, + { name: "Contato", href: "#contact" }, + ], + actions: { + login: { label: "Entrar", href: "/login" }, + signup: { label: "Começar Grátis", href: "/signup" }, + }, + }, + plans: [ + { + name: "Free", + checkout: "https://www.softwareai.site/signup?plan=free" + }, + { + name: "Premium", + checkout: "https://checkout.stripe.com/pay/premium123" + }, + { + name: "Pro", + checkout: "https://checkout.stripe.com/pay/pro123" + } + ], +}, + +]; diff --git a/Front-End/src/pages/Billing.tsx b/Front-End/src/pages/Billing.tsx new file mode 100644 index 00000000..4278a9bf --- /dev/null +++ b/Front-End/src/pages/Billing.tsx @@ -0,0 +1,242 @@ +import React, { useEffect, useState } from 'react' +import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card' +import { Button } from '@/components/ui/button' +import { Badge } from '@/components/ui/badge' + +type AccountData = { + user_id: number + email: string + planName: string + planExpiresAt: string | null + tokensUsed: number + tokenLimit: number + remainingTokens: number +} + +const samplePlans = [ + { + id: 'free', + name: 'Free', + price: 'R$ 0/mês', + features: ['300k tokens / mês', 'Suporte via docs', 'Limitações básicas'] + }, + { + id: 'pro', + name: 'Pro', + price: 'R$ 49/mês', + features: ['1M tokens / mês', 'Suporte por e-mail', 'Renovação automática'] + }, + { + id: 'business', + name: 'Business', + price: 'R$ 249/mês', + features: ['Tokens ilimitados', 'Suporte prioritário', 'Conta multi-usuário'] + } +] + +const BillingPage = () => { + const [account, setAccount] = useState(null) + const [loading, setLoading] = useState(false) + const [actionLoading, setActionLoading] = useState(null) + const [error, setError] = useState(null) + + const backend = import.meta.env.VITE_BACK_END || '' + const email = localStorage.getItem("user_email") || "" + const password = localStorage.getItem("user_senha") || "" + const accessToken = localStorage.getItem("access_token") || "" + + useEffect(() => { + fetchAccount() + }, []) + + async function fetchAccount() { + setLoading(true) + setError(null) + try { + const res = await fetch(`${backend}/api/myaccount?email=${email}&password=${password}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'X-API-TOKEN': accessToken + } + }) + if (!res.ok) throw new Error('Falha ao buscar dados da conta') + const data = await res.json() + setAccount({ + user_id: data.user_id, + email: data.email, + planName: data.planName || 'Free', + planExpiresAt: data.planExpiresAt || null, + tokensUsed: data.tokensUsed || 0, + tokenLimit: data.tokenLimit || 0, + remainingTokens: data.remainingTokens || 0 + }) + } catch (err: any) { + setError(err.message || 'Erro desconhecido') + } finally { + setLoading(false) + } + } + + function calcPercent(used: number, limit: number) { + if (limit === 0) return 0 + return Math.min(100, Math.round((used / limit) * 100)) + } + + async function handleRenew() { + if (!account) return + setActionLoading('renew') + try { + const res = await fetch(`${backend}/api/renew-plan`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-API-TOKEN': accessToken + }, + body: JSON.stringify({ plan: account.planName }) + }) + if (!res.ok) throw new Error('Falha ao renovar o plano') + await fetchAccount() + } catch (err: any) { + setError(err.message || 'Erro na renovação') + } finally { + setActionLoading(null) + } + } + + async function handleSubscribe(planId: string) { + setActionLoading(planId) + try { + const res = await fetch(`${backend}/api/subscribe`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-API-TOKEN': accessToken + }, + body: JSON.stringify({ planId }) + }) + if (!res.ok) { + const body = await res.json().catch(() => ({})) + throw new Error(body.error || 'Falha ao assinar plano') + } + await fetchAccount() + } catch (err: any) { + setError(err.message || 'Erro ao assinar plano') + } finally { + setActionLoading(null) + } + } + + return ( +
+

Billing — Minha conta

+ + {error && ( +
{error}
+ )} + +
+ {/* Left column: account summary */} +
+ + + Plano atual + + + {loading || !account ? ( +
Carregando...
+ ) : ( + <> +
+
+
{account.planName}
+
Expira em: {account.planExpiresAt ?? 'N/A'}
+
+
+ {account.remainingTokens} tokens restantes +
+
+ +
+
Uso de tokens: {account.tokensUsed} / {account.tokenLimit}
+
+
+
+
+ +
+
+ + )} + + + + + + Tokens consumidos + + + {account ? ( + <> +
{account.tokensUsed}
+
Limite: {account.tokenLimit}
+
+
+
+ + ) : ( +
+ )} + + + + + + Ações + + +
+ + +
+
+
+
+ + {/* Right column: plans */} +
+
+ {samplePlans.map((p) => ( + + + {p.name} + + +
+
{p.price}
+
    + {p.features.map((f, i) => ( +
  • • {f}
  • + ))} +
+
+ +
+ +
+
+
+ ))} +
+
+
+ +
+ ) +} + +export default BillingPage diff --git a/Front-End/src/pages/Index.tsx b/Front-End/src/pages/Index.tsx deleted file mode 100644 index 99637ff1..00000000 --- a/Front-End/src/pages/Index.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// Update this page (the content is just a fallback if you fail to update the page) - -const Index = () => { - return ( -
-
-

Welcome to Your Blank App

-

Start building your amazing project here!

-
-
- ); -}; - -export default Index; diff --git a/Front-End/src/pages/Invoices.tsx b/Front-End/src/pages/Invoices.tsx new file mode 100644 index 00000000..a9480b5a --- /dev/null +++ b/Front-End/src/pages/Invoices.tsx @@ -0,0 +1,255 @@ +import React, { useEffect, useState } from 'react' +import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Select } from '@/components/ui/select' + +type Invoice = { + id: string + number: string + date: string + amount: number + currency?: string + status: 'paid' | 'pending' | 'failed' + planName?: string + pdfUrl?: string | null + lines?: Array<{ description: string; qty?: number; price: number }> +} + +const InvoicesPage = () => { + const [invoices, setInvoices] = useState([]) + const [loading, setLoading] = useState(false) + const [error, setError] = useState(null) + const [page, setPage] = useState(1) + const [pageSize] = useState(12) + const [total, setTotal] = useState(0) + const [filterStatus, setFilterStatus] = useState<'all' | Invoice['status']>('all') + const [query, setQuery] = useState('') + const [selectedInvoice, setSelectedInvoice] = useState(null) + + const backend = import.meta.env.VITE_BACK_END || '' + const email = localStorage.getItem("user_email") || "" + const password = localStorage.getItem("user_senha") || "" + const accessToken = localStorage.getItem("access_token") || "" + + useEffect(() => { + fetchInvoices() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [page, filterStatus]) + + async function fetchInvoices() { + setLoading(true) + setError(null) + try { + const params = new URLSearchParams() + params.set('page', String(page)) + params.set('limit', String(pageSize)) + params.set('email', String(email)) + params.set('password', String(password)) + if (filterStatus !== 'all') params.set('status', filterStatus) + if (query) params.set('q', query) + + const res = await fetch(`${backend}/api/invoices?${params.toString()}`, { + headers: { + 'Content-Type': 'application/json', + 'X-API-TOKEN': accessToken + } + }) + + if (!res.ok) throw new Error('Falha ao buscar faturas') + + const body = await res.json() + // Espera: { invoices: [...], total: number } + setInvoices(body.invoices || []) + setTotal(body.total || 0) + } catch (err: any) { + setError(err.message || 'Erro desconhecido') + } finally { + setLoading(false) + } + } + + function formatCurrency(v: number, currency = 'BRL') { + try { + return new Intl.NumberFormat('pt-BR', { style: 'currency', currency }).format(v) + } catch { + return `${v}` + } + } + + async function handleDownload(invoice: Invoice) { + if (invoice.pdfUrl) { + window.open(invoice.pdfUrl, '_blank') + return + } + try { + const res = await fetch(`${backend}/api/invoices/${invoice.id}/download`, { + method: 'GET', + headers: { + 'X-API-TOKEN': accessToken + } + }) + if (!res.ok) throw new Error('Falha ao baixar fatura') + const blob = await res.blob() + const url = window.URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `invoice-${invoice.number}.pdf` + document.body.appendChild(a) + a.click() + a.remove() + window.URL.revokeObjectURL(url) + } catch (err: any) { + setError(err.message || 'Erro ao baixar fatura') + } + } + + async function handleView(invoice: Invoice) { + const params = new URLSearchParams() + params.set('email', String(email)) + params.set('password', String(password)) + if (!invoice.lines) { + try { + const res = await fetch(`${backend}/api/invoices/${invoice.id}?${params.toString()}`, { + headers: { + 'X-API-TOKEN': accessToken + } + }) + if (res.ok) { + const body = await res.json() + setSelectedInvoice({ ...invoice, ...body }) + return + } + } catch (e) { + } + } + setSelectedInvoice(invoice) + } + + function closeModal() { + setSelectedInvoice(null) + } + + const totalPages = Math.max(1, Math.ceil(total / pageSize)) + + return ( +
+
+

Faturas

+
+ +
+
+ +
+ setQuery(e.target.value)} /> + +
+ +
+
+ + + + Lista de faturas + + + {loading ? ( +
Carregando faturas...
+ ) : error ? ( +
{error}
+ ) : invoices.length === 0 ? ( +
Sem faturas encontradas.
+ ) : ( +
+ + + + + + + + + + + + + {invoices.map(inv => ( + + + + + + + + + ))} + +
#DataPlanoValorStatusAções
{inv.number}{new Date(inv.date).toLocaleString()}{inv.planName || '—'}{formatCurrency(inv.amount, inv.currency || 'BRL')}{inv.status} +
+ + +
+
+ +
+
Mostrando {invoices.length} de {total} faturas
+
+ +
{page} / {totalPages}
+ +
+
+
+ )} +
+
+ + {/* Modal simples de fatura */} + {selectedInvoice && ( +
+
+
+
+

Fatura #{selectedInvoice.number}

+
{new Date(selectedInvoice.date).toLocaleString()}
+
+
+ + +
+
+ +
+
+ Plano: {selectedInvoice.planName || '—'} +
+
+ Valor: {formatCurrency(selectedInvoice.amount, selectedInvoice.currency || 'BRL')} +
+ +
+ Itens: +
    + {selectedInvoice.lines && selectedInvoice.lines.length > 0 ? ( + selectedInvoice.lines.map((l, i) => ( +
  • {l.description} — {l.qty ? `${l.qty} x ` : ''}{formatCurrency(l.price)}
  • + )) + ) : ( +
  • Sem detalhamento disponível.
  • + )} +
+
+
+
+
+ )} +
+ ) +} +export default InvoicesPage diff --git a/Front-End/src/pages/Landingpage.tsx b/Front-End/src/pages/Landingpage.tsx new file mode 100644 index 00000000..cebac923 --- /dev/null +++ b/Front-End/src/pages/Landingpage.tsx @@ -0,0 +1,23 @@ +import { Header } from "@/components/header"; +import { HeroSection } from "@/components/hero-section"; +import { FeaturesSection } from "@/components/features-section"; +import { PricingSection } from "@/components/pricing-section"; +import { CTASection } from "@/components/cta-section"; +import { Footer } from "@/components/footer"; + +const Index = () => { + return ( +
+
+
+ + + + +
+
+
+ ); +}; + +export default Index; diff --git a/Front-End/src/pages/MyAccount.tsx b/Front-End/src/pages/MyAccount.tsx new file mode 100644 index 00000000..7c68493c --- /dev/null +++ b/Front-End/src/pages/MyAccount.tsx @@ -0,0 +1,150 @@ +// webproject\src\components\MyAccount.tsx +import { useEffect, useState } from "react" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Badge } from "@/components/ui/badge" +import { Mail, Lock, Key, Zap, Calendar, RefreshCw } from "lucide-react" + +interface AccountData { + email: string + password: string + accessToken: string + planExpiresAt: string + tokensUsed: number + tokenLimit: number + tokenPercentUsed: number +} + +const MyAccount = () => { + const [account, setAccount] = useState({ + email: "", + password: "", + accessToken: "", + planExpiresAt: "N/A", + tokensUsed: 0, + tokenLimit: 0, + tokenPercentUsed: 0, + }) + const [isLoading, setIsLoading] = useState(false) + + const backendUrl = import.meta.env.VITE_BACK_END + const email = localStorage.getItem("user_email") || "" + const password = localStorage.getItem("user_senha") || "" + const accessToken = localStorage.getItem("access_token") || "" + + const fetchAccountData = async () => { + if (!email || !accessToken) return + try { + setIsLoading(true) + const response = await fetch(`${backendUrl}/api/myaccount?email=${email}&password=${password}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + "X-API-TOKEN": accessToken, + }, + }) + + if (!response.ok) { + console.error("Erro ao buscar dados da conta:", response.status) + return + } + + const result = await response.json() + setAccount({ + email, + password, + accessToken, + planExpiresAt: result.planExpiresAt ?? "N/A", + tokensUsed: result.tokensUsed ?? 0, + tokenLimit: result.tokenLimit ?? 0, + tokenPercentUsed: result.tokenPercentUsed ?? 0, + }) + } catch (err) { + console.error("Erro ao carregar conta:", err) + } finally { + setIsLoading(false) + } + } + + useEffect(() => { + fetchAccountData() + }, []) + + return ( +
+
+

Minha Conta

+ +
+ + + + Informações Pessoais + + +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+ +
+
+ + + + Plano & Tokens + + +
+ + Expiração do Plano + + {account.planExpiresAt} +
+ +
+ + Tokens Consumidos + + + {account.tokensUsed.toLocaleString()} / {account.tokenLimit.toLocaleString()} ( + {account.tokenPercentUsed}%) + +
+
+
+
+ ) +} + +export default MyAccount diff --git a/README.md b/README.md index 23c070bc..9572147c 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ > > A maneira mais fácil e rápida de experimentar o poder do SoftwareAI é através da nossa plataforma oficial. > -> **Visite [www.softwareai.site](https://www.google.com/search?q=https://www.softwareai.site) para iniciar gratuitamente!** +> **Visite [www.softwareai.site](https://www.softwareai.site) para iniciar gratuitamente!**
-[Plataforma Oficial](https://www.google.com/search?q=https://www.softwareai.site) • [Documentação](https://www.google.com/search?q=%23documenta%C3%A7%C3%A3o) • [Instalação Local]() • [Arquitetura](#) +[Plataforma Oficial](https://www.softwareai.site) • [Documentação](https://www.softwareai.site/docs/api) • [Instalação Local (em breve)]() • [Arquitetura](#️-arquitetura-do-sistema-pr-ai)
diff --git a/build.py b/build.py index e93a2980..027485d3 100644 --- a/build.py +++ b/build.py @@ -10,5 +10,5 @@ def executar_comando(comando): subprocess.run(comando, shell=True) -executar_comando("docker-compose up --build -d frontend-pipeline") +executar_comando("docker-compose up --build -d ") diff --git a/docker-compose.yml b/docker-compose.yml index 524195af..8f82c231 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -71,7 +71,7 @@ services: - "4684:4684" restart: always command: > - sh -c "npm ci && npm run build && npx serve -s dist -l 4684" + sh -c "npm run dev -- --port 4684" healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:4684"] interval: 129s