main
230402 2025-12-15 13:20:44 +00:00
parent 9f3a74e97e
commit 2cde02f49f
41 changed files with 1663 additions and 145 deletions

View File

@ -0,0 +1,3 @@
<component name="ProjectDictionaryState">
<dictionary name="project" />
</component>

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:tools="http://schemas.android.com/tools">
<application <application
android:allowBackup="true" android:allowBackup="true"
@ -11,15 +10,26 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.Finzora"> android:theme="@style/Theme.Finzora">
<!-- This is the main activity that launches when the app starts -->
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<!-- Other activities in your application -->
<activity
android:name=".RegisterActivity"
android:exported="false" />
<activity
android:name=".HomeActivity"
android:exported="false" />
</application> </application>
</manifest> </manifest>

View File

@ -1,11 +1,43 @@
package com.example.finzora; package com.example.finzora;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class HomeActivity extends AppCompatActivity {
public class HomeActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// Criar layout SIMPLES programaticamente
TextView textView = new TextView(this);
textView.setText("Bem-vindo ao Finzora!");
textView.setTextSize(24);
textView.setPadding(50, 100, 50, 50);
Button logoutBtn = new Button(this);
logoutBtn.setText("LOGOUT");
logoutBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(HomeActivity.this, "Logout realizado", Toast.LENGTH_SHORT).show();
finish(); // Volta para MainActivity
}
});
androidx.appcompat.widget.LinearLayoutCompat layout = new androidx.appcompat.widget.LinearLayoutCompat(this);
layout.setOrientation(androidx.appcompat.widget.LinearLayoutCompat.VERTICAL);
layout.setGravity(android.view.Gravity.CENTER);
layout.addView(textView);
layout.addView(logoutBtn);
setContentView(layout);
Toast.makeText(this, "Home Activity carregada!", Toast.LENGTH_SHORT).show();
} }
} }

View File

@ -1,57 +1,175 @@
package com.example.finzora; package com.example.finzora;
import androidx.activity.OnBackPressedCallback;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
EditText inputEmail, inputPassword; // Declaração das variáveis
Button btnLogin; private EditText inputEmail, inputPassword;
private Button btnLogin;
private TextView btnRegister;
// Credenciais de exemplo (podes mudar) // Credenciais para teste
private final String USER_EMAIL = "admin@gmail.com"; private final String TEST_EMAIL = "teste@email.com";
private final String USER_PASSWORD = "123456"; private final String TEST_PASSWORD = "123456";
// Para controlar o double back press
private boolean doubleBackToExitPressedOnce = false;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
inputEmail = findViewById(R.id.inputEmail); // Configurar o botão voltar (nova forma)
inputPassword = findViewById(R.id.inputPassword); setupBackButton();
btnLogin = findViewById(R.id.btnLogin);
btnLogin.setOnClickListener(new View.OnClickListener() { // Inicializar views
initializeViews();
// Configurar botão de Login
setupLoginButton();
// Configurar link de Registro
setupRegisterButton();
}
private void setupBackButton() {
// Nova forma de tratar o botão voltar (Android 13+)
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override @Override
public void onClick(View v) { public void handleOnBackPressed() {
String email = inputEmail.getText().toString().trim(); // Para sair do app com double back press
String password = inputPassword.getText().toString().trim(); if (doubleBackToExitPressedOnce) {
// Se já pressionou uma vez, sai do app
if (email.isEmpty() || password.isEmpty()) {
Toast.makeText(MainActivity.this, "Preencha todos os campos", Toast.LENGTH_SHORT).show();
return;
}
// Verificação simples
if (email.equals(USER_EMAIL) && password.equals(USER_PASSWORD)) {
Toast.makeText(MainActivity.this, "Login efetuado!", Toast.LENGTH_SHORT).show();
// Ir para a próxima página
Intent intent = new Intent(MainActivity.this, HomeActivity.class);
startActivity(intent);
finish(); finish();
} else { } else {
Toast.makeText(MainActivity.this, "Email ou palavra-passe incorretos", Toast.LENGTH_SHORT).show(); // Primeira vez que pressiona
doubleBackToExitPressedOnce = true;
Toast.makeText(MainActivity.this,
"Pressione VOLTAR novamente para sair",
Toast.LENGTH_SHORT).show();
// Reset após 2 segundos
getWindow().getDecorView().postDelayed(() ->
doubleBackToExitPressedOnce = false, 2000);
} }
} }
}); });
} }
}
private void initializeViews() {
inputEmail = findViewById(R.id.inputEmail);
inputPassword = findViewById(R.id.inputPassword);
btnLogin = findViewById(R.id.btnLogin);
btnRegister = findViewById(R.id.btnRegister);
}
private void setupLoginButton() {
btnLogin.setOnClickListener(v -> realizarLogin());
}
private void setupRegisterButton() {
btnRegister.setOnClickListener(v -> abrirTelaRegistro());
}
private void realizarLogin() {
// Obter valores dos campos
String email = inputEmail.getText().toString().trim();
String password = inputPassword.getText().toString().trim();
// Validar campos vazios
if (email.isEmpty()) {
inputEmail.setError("Digite seu email");
inputEmail.requestFocus();
return;
}
if (password.isEmpty()) {
inputPassword.setError("Digite sua senha");
inputPassword.requestFocus();
return;
}
// Validar formato do email
if (!isValidEmail(email)) {
inputEmail.setError("Digite um email válido");
inputEmail.requestFocus();
return;
}
// Verificar credenciais
if (email.equals(TEST_EMAIL) && password.equals(TEST_PASSWORD)) {
// Login bem-sucedido
Toast.makeText(this, "Login realizado com sucesso!", Toast.LENGTH_SHORT).show();
// Ir para HomeActivity
Intent intent = new Intent(MainActivity.this, HomeActivity.class);
startActivity(intent);
// Fechar esta activity
finish();
} else {
// Credenciais incorretas
Toast.makeText(this, "Email ou senha incorretos", Toast.LENGTH_SHORT).show();
inputPassword.setText("");
inputPassword.requestFocus();
}
}
private boolean isValidEmail(String email) {
return email.contains("@") && email.contains(".");
}
private void abrirTelaRegistro() {
try {
Intent intent = new Intent(MainActivity.this, RegisterActivity.class);
startActivityForResult(intent, 100);
} catch (Exception e) {
Toast.makeText(this, "Erro ao abrir registro", Toast.LENGTH_LONG).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100 && resultCode == RESULT_OK && data != null) {
String novoEmail = data.getStringExtra("EMAIL");
String novoPassword = data.getStringExtra("PASSWORD");
if (novoEmail != null && novoPassword != null) {
inputEmail.setText(novoEmail);
inputPassword.setText(novoPassword);
Toast.makeText(this, "Conta criada! Faça login.", Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onResume() {
super.onResume();
// Limpar campo da senha quando voltar
if (inputPassword != null) {
inputPassword.setText("");
}
// Dar foco ao campo de email
if (inputEmail != null) {
inputEmail.requestFocus();
}
// Resetar o double back press
doubleBackToExitPressedOnce = false;
}
}

View File

@ -0,0 +1,138 @@
package com.example.finzora;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import com.example.finzora.MainActivity;
public class OnboardingActivity extends AppCompatActivity {
private ViewPager2 viewPager;
private Button btnSkip, btnNext;
private ImageButton btnPrev;
private LinearLayout dotsLayout;
private int currentPage = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_onboarding);
// Inicializar views
viewPager = findViewById(R.id.viewPager);
btnSkip = findViewById(R.id.btnSkip);
btnNext = findViewById(R.id.btnNext);
btnPrev = findViewById(R.id.btnPrev);
dotsLayout = findViewById(R.id.dotsLayout);
// Configurar ViewPager
OnboardingAdapter adapter = new OnboardingAdapter();
viewPager.setAdapter(adapter);
// Configurar dots indicadores
setupDots();
// Configurar botões
setupButtons();
// Ouvir mudanças de página
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
currentPage = position;
updateDots(position);
updateButtons(position);
}
});
}
private void setupDots() {
dotsLayout.removeAllViews();
for (int i = 0; i < 5; i++) {
View dot = new View(this);
dot.setBackgroundColor(Color.GRAY);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(16, 16);
params.setMargins(8, 0, 8, 0);
dot.setLayoutParams(params);
dotsLayout.addView(dot);
}
updateDots(0);
}
private void updateDots(int position) {
for (int i = 0; i < dotsLayout.getChildCount(); i++) {
View dot = dotsLayout.getChildAt(i);
if (i == position) {
dot.setBackgroundColor(Color.parseColor("#2196F3")); // Azul Finzora
dot.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200).start();
} else {
dot.setBackgroundColor(Color.GRAY);
dot.animate().scaleX(1f).scaleY(1f).setDuration(200).start();
}
}
}
private void setupButtons() {
btnSkip.setOnClickListener(v -> skipTutorial());
btnNext.setOnClickListener(v -> nextPage());
btnPrev.setOnClickListener(v -> previousPage());
}
private void updateButtons(int position) {
if (position == 4) { // Última página
btnNext.setText("COMEÇAR");
btnPrev.setVisibility(View.VISIBLE);
btnSkip.setVisibility(View.GONE);
} else if (position == 0) { // Primeira página
btnNext.setText("PRÓXIMO");
btnPrev.setVisibility(View.INVISIBLE);
btnSkip.setVisibility(View.VISIBLE);
} else { // Páginas do meio
btnNext.setText("PRÓXIMO");
btnPrev.setVisibility(View.VISIBLE);
btnSkip.setVisibility(View.VISIBLE);
}
}
private void nextPage() {
if (currentPage < 4) {
viewPager.setCurrentItem(currentPage + 1, true);
} else {
startMainApp();
}
}
private void previousPage() {
if (currentPage > 0) {
viewPager.setCurrentItem(currentPage - 1, true);
}
}
private void skipTutorial() {
startMainApp();
}
private void startMainApp() {
Intent intent = new Intent(OnboardingActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
@Override
public void onBackPressed() {
// Pressionar back pula direto para o app
startMainApp();
}
}

View File

@ -0,0 +1,88 @@
package com.example.finzora;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class OnboardingAdapter extends RecyclerView.Adapter<OnboardingAdapter.ViewHolder> {
// Títulos das páginas
private final String[] titles = {
"Bem-vindo ao Finase!",
"Registe as Suas Transações",
"Planeie o Seu Orçamento",
"Visualize os Seus Dados",
"Receba Dicas Personalizadas"
};
// Descrições das páginas
private final String[] descriptions = {
"A sua aplicação pessoal de gestão financeira. Controle as suas finanças de forma simples e intuitiva.",
"Adicione receitas e despesas facilmente. Organize tudo por categorias para ter uma visão clara dos seus gastos.",
"Defina limites e controle os gastos. Crie orçamentos mensais e receba alertas quando exceder os limites.",
"Veja gráficos interativos com a distribuição dos seus gastos, tendências mensais e comparações detalhadas.",
"Conselhos baseados nos seus hábitos. O Finase analisa os seus gastos e fornece dicas para melhorar a sua saúde financeira."
};
// Cores para os ícones (vamos usar círculos coloridos)
private final int[] colors = {
android.R.color.holo_blue_dark, // Azul
android.R.color.holo_green_dark, // Verde
android.R.color.holo_orange_dark, // Laranja
android.R.color.holo_purple, // Roxo
android.R.color.holo_red_dark // Vermelho
};
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_onboarding, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// Configurar título e descrição
holder.title.setText(titles[position]);
holder.description.setText(descriptions[position]);
// Criar um círculo colorido como "ícone"
View circle = holder.itemView.findViewById(R.id.circleView);
if (circle != null) {
circle.setBackgroundColor(holder.itemView.getContext()
.getResources().getColor(colors[position]));
}
// Animação de entrada
holder.itemView.setAlpha(0f);
holder.itemView.setTranslationY(50f);
holder.itemView.animate()
.alpha(1f)
.translationY(0f)
.setDuration(500)
.setStartDelay(position * 100L)
.start();
}
@Override
public int getItemCount() {
return 5; // 5 páginas do tutorial
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView title;
TextView description;
ViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
description = itemView.findViewById(R.id.description);
}
}
}

View File

@ -0,0 +1,132 @@
package com.example.finzora;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class RegisterActivity extends AppCompatActivity {
// Declaração SIMPLES
EditText inputNome, inputEmail, inputPassword, inputConfirmPassword;
Button btnRegister, btnLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
// Mensagem de debug
Toast.makeText(this, "RegisterActivity iniciada", Toast.LENGTH_SHORT).show();
// Inicializar views
initViews();
// Configurar botões
setupButtons();
}
private void initViews() {
inputNome = findViewById(R.id.inputName);
inputEmail = findViewById(R.id.inputEmail);
inputPassword = findViewById(R.id.inputPassword);
inputConfirmPassword = findViewById(R.id.inputConfirmPassword);
btnRegister = findViewById(R.id.btnRegister);
btnLogin = findViewById(R.id.btnLogin);
// Verificar se encontrou TODAS as views
checkViews();
}
private void checkViews() {
String mensagem = "Views encontradas: ";
if (inputNome != null) mensagem += "Nome ✓ ";
if (inputEmail != null) mensagem += "Email ✓ ";
if (inputPassword != null) mensagem += "Password ✓ ";
if (inputConfirmPassword != null) mensagem += "ConfirmPassword ✓ ";
if (btnRegister != null) mensagem += "BtnRegister ✓ ";
if (btnLogin != null) mensagem += "BtnLogin ✓ ";
Toast.makeText(this, mensagem, Toast.LENGTH_LONG).show();
}
private void setupButtons() {
// Botão Registrar
btnRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
registrarConta();
}
});
// Botão Voltar
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish(); // Volta para MainActivity
}
});
}
private void registrarConta() {
// Obter valores
String nome = inputNome.getText().toString().trim();
String email = inputEmail.getText().toString().trim();
String password = inputPassword.getText().toString();
String confirmPassword = inputConfirmPassword.getText().toString();
// Validar
if (nome.isEmpty()) {
Toast.makeText(this, "Digite seu nome", Toast.LENGTH_SHORT).show();
inputNome.requestFocus();
return;
}
if (email.isEmpty()) {
Toast.makeText(this, "Digite seu email", Toast.LENGTH_SHORT).show();
inputEmail.requestFocus();
return;
}
if (password.isEmpty()) {
Toast.makeText(this, "Crie uma palavra-passe", Toast.LENGTH_SHORT).show();
inputPassword.requestFocus();
return;
}
if (confirmPassword.isEmpty()) {
Toast.makeText(this, "Confirme a palavra-passe", Toast.LENGTH_SHORT).show();
inputConfirmPassword.requestFocus();
return;
}
if (!password.equals(confirmPassword)) {
Toast.makeText(this, "As palavras-passe não são iguais", Toast.LENGTH_SHORT).show();
inputConfirmPassword.requestFocus();
return;
}
if (password.length() < 6) {
Toast.makeText(this, "A palavra-passe deve ter pelo menos 6 caracteres", Toast.LENGTH_SHORT).show();
inputPassword.requestFocus();
return;
}
// Sucesso!
Toast.makeText(this, "Conta criada com sucesso!", Toast.LENGTH_SHORT).show();
// Pode passar os dados de volta para o login
Intent data = new Intent();
data.putExtra("EMAIL", email);
data.putExtra("PASSWORD", password);
setResult(RESULT_OK, data);
// Fechar esta activity
finish();
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1"
android:toXScale="1.1"
android:fromYScale="1"
android:toYScale="1.1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:repeatCount="infinite"
android:repeatMode="reverse" />
</set>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="100%"
android:toXDelta="0"
android:duration="400" />
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:duration="400" />
</set>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<translate
android:fromXDelta="0"
android:toXDelta="-100%"
android:duration="400" />
<alpha
android:fromAlpha="1"
android:toAlpha="0"
android:duration="400" />
</set>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="50"
android:toYDelta="0"
android:duration="500" />
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:duration="500" />
</set>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Cores principais do Finzora (Azul corporativo) -->
<color name="primary">#2196F3</color> <!-- Azul principal -->
<color name="primary_dark">#1976D2</color> <!-- Azul escuro -->
<color name="primary_light">#BBDEFB</color> <!-- Azul claro -->
<!-- Cores de acento -->
<color name="accent">#FF9800</color> <!-- Laranja para highlights -->
<color name="accent_dark">#F57C00</color> <!-- Laranja escuro -->
<!-- Cores para transações financeiras -->
<color name="income_green">#4CAF50</color> <!-- Verde para receitas -->
<color name="expense_red">#F44336</color> <!-- Vermelho para despesas -->
<color name="warning_yellow">#FFC107</color><!-- Amarelo para alertas -->
<color name="savings_teal">#009688</color> <!-- Verde-azulado para poupança -->
<!-- Cores de texto -->
<color name="text_primary">#212121</color> <!-- Texto principal (quase preto) -->
<color name="text_secondary">#757575</color> <!-- Texto secundário (cinza) -->
<color name="text_hint">#BDBDBD</color> <!-- Texto de hint/placeholder -->
<color name="text_white">#FFFFFF</color> <!-- Texto branco (sobre fundos escuros) -->
<!-- Cores de fundo -->
<color name="background_light">#F5F5F5</color> <!-- Fundo claro das telas -->
<color name="background_card">#FFFFFF</color> <!-- Fundo de cards -->
<color name="background_dark">#263238</color> <!-- Fundo escuro (se necessário) -->
<!-- Cores de bordas e divisórias -->
<color name="border_light">#E0E0E0</color> <!-- Bordas claras -->
<color name="border_dark">#BDBDBD</color> <!-- Bordas escuras -->
<!-- Cores de estado -->
<color name="disabled">#9E9E9E</color> <!-- Elementos desabilitados -->
<color name="error">#D32F2F</color> <!-- Mensagens de erro -->
<color name="success">#388E3C</color> <!-- Mensagens de sucesso -->
<!-- Cores para categorias de despesas -->
<color name="category_food">#FF9800</color> <!-- Alimentação -->
<color name="category_transport">#3F51B5</color> <!-- Transporte -->
<color name="category_housing">#795548</color> <!-- Moradia -->
<color name="category_entertainment">#9C27B0</color> <!-- Entretenimento -->
<color name="category_shopping">#E91E63</color> <!-- Compras -->
<color name="category_health">#4CAF50</color> <!-- Saúde -->
<color name="category_education">#2196F3</color> <!-- Educação -->
<color name="category_other">#607D8B</color> <!-- Outros -->
</resources>

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- App Info -->
<string name="app_name">Finzora</string>
<string name="app_slogan">Sua gestão financeira inteligente</string>
<!-- Login Screen -->
<string name="login_title">Bem-vindo ao Finzora</string>
<string name="email_hint">Email</string>
<string name="password_hint">Palavra-passe</string>
<string name="login_button">ENTRAR</string>
<string name="forgot_password">Esqueceu a palavra-passe?</string>
<string name="register_prompt">Não tem conta?</string>
<string name="register_link">Registre-se aqui</string>
<!-- Register Screen -->
<string name="register_title">Criar Nova Conta</string>
<string name="name_hint">Nome completo</string>
<string name="confirm_password_hint">Confirmar palavra-passe</string>
<string name="register_button">REGISTRAR</string>
<string name="login_prompt">Já tem uma conta?</string>
<string name="login_link">Faça login</string>
<!-- Onboarding/Tutorial -->
<string name="onboarding_welcome_title">Bem-vindo ao Finzora!</string>
<string name="onboarding_welcome_desc">A sua aplicação pessoal de gestão financeira. Controle as suas finanças de forma simples e intuitiva.</string>
<string name="onboarding_transactions_title">Registe as Suas Transações</string>
<string name="onboarding_transactions_desc">Adicione receitas e despesas facilmente. Organize tudo por categorias para ter uma visão clara dos seus gastos.</string>
<string name="onboarding_budget_title">Planeie o Seu Orçamento</string>
<string name="onboarding_budget_desc">Defina limites e controle os gastos. Crie orçamentos mensais e receba alertas quando exceder os limites.</string>
<string name="onboarding_charts_title">Visualize os Seus Dados</string>
<string name="onboarding_charts_desc">Veja gráficos interativos com a distribuição dos seus gastos, tendências mensais e comparações detalhadas.</string>
<string name="onboarding_tips_title">Receba Dicas Personalizadas</string>
<string name="onboarding_tips_desc">Conselhos baseados nos seus hábitos. O Finzora analisa os seus gastos e fornece dicas para melhorar a sua saúde financeira.</string>
<string name="skip_tutorial">Saltar Tutorial</string>
<string name="next">Próximo</string>
<string name="start">Começar</string>
<!-- Dashboard/Home -->
<string name="dashboard_title">Dashboard</string>
<string name="total_balance">Saldo Total</string>
<string name="monthly_income">Receitas do Mês</string>
<string name="monthly_expense">Despesas do Mês</string>
<string name="recent_transactions">Transações Recentes</string>
<string name="view_all">Ver Tudo</string>
<string name="add_transaction">Adicionar Transação</string>
<!-- Transaction Categories -->
<string name="category_food">Alimentação</string>
<string name="category_transport">Transporte</string>
<string name="category_housing">Moradia</string>
<string name="category_entertainment">Entretenimento</string>
<string name="category_shopping">Compras</string>
<string name="category_health">Saúde</string>
<string name="category_education">Educação</string>
<string name="category_other">Outros</string>
<!-- Transaction Types -->
<string name="transaction_income">Receita</string>
<string name="transaction_expense">Despesa</string>
<!-- Messages & Errors -->
<string name="error_empty_field">Por favor, preencha este campo</string>
<string name="error_invalid_email">Digite um email válido</string>
<string name="error_password_length">A palavra-passe deve ter pelo menos 6 caracteres</string>
<string name="error_passwords_not_match">As palavras-passe não coincidem</string>
<string name="login_success">Login realizado com sucesso!</string>
<string name="register_success">Conta criada com sucesso!</string>
<string name="transaction_added">Transação adicionada!</string>
<string name="loading">A carregar…</string>
<string name="no_transactions">Nenhuma transação registada</string>
<!-- Navigation -->
<string name="nav_home">Início</string>
<string name="nav_transactions">Transações</string>
<string name="nav_budget">Orçamento</string>
<string name="nav_reports">Relatórios</string>
<string name="nav_profile">Perfil</string>
<string name="nav_logout">Sair</string>
<!-- Months (para gráficos e filtros) -->
<string name="month_jan">Jan</string>
<string name="month_feb">Fev</string>
<string name="month_mar">Mar</string>
<string name="month_apr">Abr</string>
<string name="month_may">Mai</string>
<string name="month_jun">Jun</string>
<string name="month_jul">Jul</string>
<string name="month_aug">Ago</string>
<string name="month_sep">Set</string>
<string name="month_oct">Out</string>
<string name="month_nov">Nov</string>
<string name="month_dec">Dez</string>
</resources>

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- ===== TEMA PRINCIPAL DO APP ===== -->
<style name="Theme.Finzora" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Cores principais -->
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryVariant">@color/primary_dark</item>
<item name="colorOnPrimary">@color/text_white</item>
<!-- Cores secundárias -->
<item name="colorSecondary">@color/accent</item>
<item name="colorSecondaryVariant">@color/accent_dark</item>
<item name="colorOnSecondary">@color/text_white</item>
<!-- Cores de fundo -->
<item name="android:windowBackground">@color/background_light</item>
<item name="android:colorBackground">@color/background_light</item>
<!-- Status Bar -->
<item name="android:statusBarColor">@color/primary_dark</item>
<item name="android:windowLightStatusBar">false</item>
<!-- Navigation Bar (se necessário) -->
<item name="android:navigationBarColor">@color/background_light</item>
<!-- Estilos de componentes -->
<item name="materialButtonStyle">@style/Widget.Finzora.Button.Primary</item>
<item name="textInputStyle">@style/Widget.Finzora.TextInputLayout</item>
<item name="cardViewStyle">@style/Widget.Finzora.CardView</item>
<!-- Tipografia -->
<item name="android:fontFamily">sans-serif</item>
<!-- Animações -->
<item name="android:windowAnimationStyle">@style/WindowAnimation.Finzora</item>
</style>
<!-- ===== BOTÕES ===== -->
<style name="Widget.Finzora.Button.Primary" parent="Widget.MaterialComponents.Button">
<item name="android:minHeight">56dp</item>
<item name="android:paddingVertical">16dp</item>
<item name="android:paddingHorizontal">24dp</item>
<item name="cornerRadius">28dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
<item name="android:letterSpacing">0.02</item>
</style>
<style name="Widget.Finzora.Button.Secondary" parent="Widget.Finzora.Button.Primary">
<item name="backgroundTint">@color/background_card</item>
<item name="android:textColor">@color/primary</item>
<item name="strokeColor">@color/primary</item>
<item name="strokeWidth">2dp</item>
</style>
<style name="Widget.Finzora.Button.Text" parent="Widget.AppCompat.Button.Borderless">
<item name="android:textColor">@color/primary</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">normal</item>
<item name="android:padding">8dp</item>
</style>
<!-- ===== TEXT INPUTS ===== -->
<style name="Widget.Finzora.TextInputLayout" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<item name="boxStrokeColor">@color/border_light</item>
<item name="boxStrokeWidth">1dp</item>
<item name="boxCornerRadiusTopStart">8dp</item>
<item name="boxCornerRadiusTopEnd">8dp</item>
<item name="boxCornerRadiusBottomStart">8dp</item>
<item name="boxCornerRadiusBottomEnd">8dp</item>
<item name="hintTextColor">@color/text_hint</item>
<item name="errorTextColor">@color/error</item>
<item name="android:paddingVertical">4dp</item>
</style>
<!-- ===== CARDS ===== -->
<style name="Widget.Finzora.CardView" parent="CardView">
<item name="cardCornerRadius">16dp</item>
<item name="cardElevation">4dp</item>
<item name="cardUseCompatPadding">true</item>
<item name="cardBackgroundColor">@color/background_card</item>
</style>
<style name="Widget.Finzora.CardView.Elevated" parent="Widget.Finzora.CardView">
<item name="cardElevation">8dp</item>
<item name="cardMaxElevation">12dp</item>
</style>
<!-- ===== TYPOGRAPHY ===== -->
<style name="TextAppearance.Finzora.Headline1">
<item name="android:textSize">24sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/text_primary</item>
<item name="android:letterSpacing">0.01</item>
</style>
<style name="TextAppearance.Finzora.Headline2">
<item name="android:textSize">20sp</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/text_primary</item>
</style>
<style name="TextAppearance.Finzora.Body1">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/text_primary</item>
<item name="android:lineSpacingExtra">4dp</item>
</style>
<style name="TextAppearance.Finzora.Body2">
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/text_secondary</item>
</style>
<style name="TextAppearance.Finzora.Caption">
<item name="android:textSize">12sp</item>
<item name="android:textColor">@color/text_hint</item>
</style>
<!-- ===== BADGES & CHIPS ===== -->
<style name="Widget.Finzora.Chip" parent="Widget.MaterialComponents.Chip.Choice">
<item name="chipBackgroundColor">@color/primary_light</item>
<item name="chipStrokeColor">@color/primary</item>
<item name="chipStrokeWidth">1dp</item>
<item name="cornerRadius">16dp</item>
<item name="android:textColor">@color/primary</item>
</style>
<!-- ===== ANIMAÇÕES ===== -->
<style name="WindowAnimation.Finzora">
<item name="android:windowEnterAnimation">@anim/slide_in_right</item>
<item name="android:windowExitAnimation">@anim/slide_out_left</item>
<item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item>
<item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
<item name="android:activityCloseEnterAnimation">@android:anim/fade_in</item>
<item name="android:activityCloseExitAnimation">@android:anim/fade_out</item>
</style>
<!-- ===== DIALOGS ===== -->
<style name="Theme.Finzora.Dialog" parent="Theme.MaterialComponents.Light.Dialog">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryVariant">@color/primary_dark</item>
<item name="colorOnPrimary">@color/text_white</item>
<item name="cornerRadius">16dp</item>
</style>
<!-- ===== TOOLBAR ===== -->
<style name="Widget.Finzora.Toolbar" parent="Widget.MaterialComponents.Toolbar.Primary">
<item name="titleTextColor">@color/text_white</item>
<item name="subtitleTextColor">@color/primary_light</item>
<item name="android:minHeight">?attr/actionBarSize</item>
<item name="elevation">4dp</item>
</style>
</resources>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#2196F3" />
<corners android:radius="24dp" />
</shape>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E3F2FD" />
<corners android:radius="12dp" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="12dp"
android:height="12dp" />
<solid
android:color="#2196F3" /> <!-- Azul Finzora -->
</shape>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="8dp"
android:height="8dp" />
<solid
android:color="#CCCCCC" /> <!-- Cinza claro -->
</shape>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<corners android:radius="8dp" />
<stroke
android:width="1dp"
android:color="#E0E0E0" />
<padding
android:left="8dp"
android:top="8dp"
android:right="8dp"
android:bottom="8dp" />
</shape>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#2196F3"
android:endColor="#1976D2"
android:angle="135" />
<corners android:radius="16dp" />
</shape>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp" android:viewportWidth="24"
android:viewportHeight="24">
<!-- Branco (para botão azul) -->
<path
android:fillColor="#FFFFFF"
android:pathData="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
</vector>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
tools:ignore="ExtraText">
<!-- Laranja -->
<path
android:fillColor="#FF9800"
android:pathData="M19,14V6C19,4.9 18.1,4 17,4H3C1.9,4 1,4.9 1,6V14C1,15.1 1.9,16 3,16H17C18.1,16 19,15.1 19,14ZM17,14H3V6H17V14ZM10,7C8.34,7 7,8.34 7,10C7,11.66 8.34,13 10,13C11.66,13 13,11.66 13,10C13,8.34 11.66,7 10,7ZM23,7V18C23,19.1 22.1,20 21,20H4V18H21V7H23Z" />
</vector>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
tools:ignore="ExtraText">
<!-- Roxo -->
<path
android:fillColor="#9C27B0"
android:pathData="M19,3H5C3.9,3 3,3.9 3,5V19C3,20.1 3.9,21 5,21H19C20.1,21 21,20.1 21,19V5C21,3.9 20.1,3 19,3ZM9,17H7V10H9V17ZM13,17H11V7H13V17ZM17,17H15V13H17V17Z" />
</vector>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<!-- Azul do Finzora -->
<path
android:fillColor="#2196F3"
android:pathData="M15.41,16.59L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.59Z" />
</vector>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
tools:ignore="ExtraText">
<!-- Ciano -->
<path
android:fillColor="#00BCD4"
android:pathData="M9,21C9,21.55 9.45,22 10,22H14C14.55,22 15,21.55 15,21V20H9V21ZM12,2C8.14,2 5,5.14 5,9C5,11.38 6.19,13.47 8,14.74V17C8,17.55 8.45,18 9,18H15C15.55,18 16,17.55 16,17V14.74C17.81,13.47 19,11.38 19,9C19,5.14 15.86,2 12,2ZM14.85,13.1L14,13.7V16H10V13.7L9.15,13.1C7.8,12.16 7,10.63 7,9C7,6.24 9.24,4 12,4C14.76,4 17,6.24 17,9C17,10.63 16.2,12.16 14.85,13.1Z" />
</vector>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#4CAF50"
android:pathData="M20,4H4C2.89,4 2,4.89 2,6V18C2,19.11 2.89,20 4,20H20C21.11,20 22,19.11 22,18V6C22,4.89 21.11,4 20,4ZM8,18H4V14H8V18ZM8,12H4V8H8V12ZM8,6H4V6H8V6ZM14,18H10V14H14V18ZM14,12H10V8H14V12ZM14,6H10V6H14V6ZM20,18H16V14H20V18ZM20,12H16V8H20V12ZM20,6H16V6H20V6Z" />
</vector>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#2196F3"
android:pathData="M12,2L15.09,8.26L22,9.27L17,14.14L18.18,21.02L12,17.77L5.82,21.02L7,14.14L2,9.27L8.91,8.26L12,2Z" />
</vector>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>

View File

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="80dp">
<!-- Cabeçalho -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="20dp"
android:gravity="center_vertical">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Finzora"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/primary" />
<ImageButton
android:id="@+id/btnMenu"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_menu"
android:background="?attr/selectableItemBackground" />
</LinearLayout>
<!-- Cards de Resumo -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:gravity="center">
<!-- Saldo Total -->
<androidx.cardview.widget.CardView
android:id="@+id/cardBalance"
android:layout_width="0dp"
android:layout_height="120dp"
android:layout_weight="1"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/gradient_primary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Saldo Total"
android:textColor="@color/white"
android:textSize="14sp"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/tvBalance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="€0.00"
android:textColor="@color/white"
android:textSize="28sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<!-- Receitas e Despesas -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<!-- Receitas -->
<androidx.cardview.widget.CardView
android:id="@+id/cardIncome"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_weight="1"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Receitas"
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/tvIncome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+€0.00"
android:textColor="@color/green"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Despesas -->
<androidx.cardview.widget.CardView
android:id="@+id/cardExpense"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_weight="1"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Despesas"
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/tvExpense"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-€0.00"
android:textColor="@color/red"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<!-- Título das Transações -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Transações Recentes"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:layout_marginStart="24dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="16dp" />
<!-- Lista de Transações -->
<LinearLayout
android:id="@+id/layoutTransactions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp" />
<!-- Espaço para o botão flutuante -->
<View
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
<!-- Botão Flutuante para Adicionar Transação -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnAddTransaction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="24dp"
android:src="@drawable/ic_add"
app:backgroundTint="@color/primary"
app:tint="@color/white" />
</ScrollView>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="20dp">
</androidx.constraintlayout.widget.ConstraintLayout> <TextView
android:id="@+id/txtWelcome"
android:text="Bem-vindo ao Finzora!"
android:textSize="24sp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@ -1,115 +1,64 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fillViewport="true" android:orientation="vertical"
android:background="#F3F6FF"> android:gravity="center"
android:padding="20dp">
<LinearLayout <!-- Título -->
android:layout_width="match_parent" <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:text="Finzora"
android:orientation="vertical" android:textSize="32sp"
android:padding="24dp"> android:textStyle="bold"
android:textColor="#2196F3"
android:layout_marginBottom="40dp" />
<!-- CARD --> <!-- Campo Email -->
<LinearLayout <EditText
android:layout_width="match_parent" android:id="@+id/inputEmail"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:background="@drawable/card_bg" android:layout_height="50dp"
android:orientation="vertical" android:hint="Email"
android:gravity="center_horizontal" android:inputType="textEmailAddress"
android:padding="24dp" android:padding="12dp"
android:elevation="6dp"> android:background="@android:drawable/editbox_background"
android:layout_marginBottom="16dp" />
<!-- LOGO --> <!-- Campo Password -->
<ImageView <EditText
android:id="@+id/logo" android:id="@+id/inputPassword"
android:layout_width="64dp" android:layout_width="match_parent"
android:layout_height="64dp" android:layout_height="50dp"
android:src="@drawable/logo_finzora" android:hint="Password"
android:layout_marginBottom="12dp" /> android:inputType="textPassword"
android:padding="12dp"
android:background="@android:drawable/editbox_background"
android:layout_marginBottom="24dp" />
<!-- TÍTULO --> <!-- Botão Login -->
<TextView <Button
android:layout_width="wrap_content" android:id="@+id/btnLogin"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:text="Finzora" android:layout_height="55dp"
android:textSize="26sp" android:text="ENTRAR"
android:textStyle="bold" android:textColor="#FFFFFF"
android:textColor="#1A1A1A" android:background="#2196F3"
android:layout_marginBottom="4dp" /> android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="20dp" />
<!-- SUBTÍTULO --> <!-- Link para Registro -->
<TextView <TextView
android:layout_width="wrap_content" android:id="@+id/btnRegister"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:text="Entre na sua conta para gerir as suas despesas" android:layout_height="wrap_content"
android:textSize="14sp" android:text="Criar nova conta"
android:textColor="#6A6A6A" android:textColor="#2196F3"
android:gravity="center" android:textSize="14sp"
android:layout_marginBottom="20dp" /> android:textStyle="bold"
android:padding="8dp" />
<!-- EMAIL -->
<EditText
android:id="@+id/inputEmail"
android:layout_width="match_parent"
android:layout_height="48dp"
android:hint="Email"
android:padding="12dp"
android:background="@drawable/edittext_bg"
android:inputType="textEmailAddress"
android:textColor="#000"
android:textColorHint="#A0A0A0"
android:layout_marginBottom="14dp" />
<!-- PASSWORD -->
<EditText
android:id="@+id/inputPassword"
android:layout_width="match_parent"
android:layout_height="48dp"
android:hint="Palavra-passe"
android:padding="12dp"
android:background="@drawable/edittext_bg"
android:inputType="textPassword"
android:textColor="#000"
android:textColorHint="#A0A0A0"
android:layout_marginBottom="18dp" />
<!-- BOTÃO -->
<Button
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Entrar"
android:textSize="16sp"
android:textColor="#FFFFFF"
android:backgroundTint="#2D54FF"
android:layout_marginBottom="12dp" />
<!-- REGISTO -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Não tem conta? "
android:textColor="#6A6A6A" />
<TextView
android:id="@+id/goToRegister"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Registar agora"
android:textColor="#2D54FF"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background">
<!-- ViewPager para as páginas -->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="@+id/controlsLayout"
android:layout_below="@+id/dotsLayout" />
<!-- Indicadores de página -->
<LinearLayout
android:id="@+id/dotsLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:orientation="horizontal" />
<!-- Controles -->
<LinearLayout
android:id="@+id/controlsLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:padding="24dp"
android:gravity="center_vertical">
<!-- Botão Anterior -->
<ImageButton
android:id="@+id/btnPrev"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_prev"
android:background="?attr/selectableItemBackground"
android:visibility="invisible" />
<!-- Botão Pular -->
<Button
android:id="@+id/btnSkip"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Saltar Tutorial"
android:textColor="@color/text_secondary"
android:background="@android:color/transparent"
android:textAllCaps="false" />
<!-- Botão Próximo -->
<Button
android:id="@+id/btnNext"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:text="Próximo"
android:textColor="@color/white"
android:background="@drawable/btn_primary"
android:textAllCaps="false"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:gravity="center" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Criar Nova Conta"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#2196F3"
android:layout_marginBottom="30dp" />
<EditText
android:id="@+id/inputName"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="Nome Completo"
android:inputType="text"
android:padding="12dp"
android:background="#F0F0F0"
android:layout_marginBottom="16dp" />
<EditText
android:id="@+id/inputEmail"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="Email"
android:inputType="textEmailAddress"
android:padding="12dp"
android:background="#F0F0F0"
android:layout_marginBottom="16dp" />
<EditText
android:id="@+id/inputPassword"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="Palavra-passe"
android:inputType="textPassword"
android:padding="12dp"
android:background="#F0F0F0"
android:layout_marginBottom="16dp" />
<EditText
android:id="@+id/inputConfirmPassword"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="Confirmar Palavra-passe"
android:inputType="textPassword"
android:padding="12dp"
android:background="#F0F0F0"
android:layout_marginBottom="24dp" />
<Button
android:id="@+id/btnRegister"
android:layout_width="match_parent"
android:layout_height="55dp"
android:text="REGISTRAR"
android:textColor="#FFFFFF"
android:background="#2196F3"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="20dp" />
<Button
android:id="@+id/btnLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="← Voltar para Login"
android:textColor="#2196F3"
android:background="@android:color/transparent" />
</LinearLayout>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="40dp">
<ImageView
android:id="@+id/onboardingImage"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginBottom="40dp" />
<TextView
android:id="@+id/onboardingTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:gravity="center"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/onboardingDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@color/text_secondary"
android:gravity="center"
android:lineSpacingExtra="4dp"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
</LinearLayout>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
android:layout_marginBottom="8dp"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<!-- Informações da transação -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tvTransactionTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/text_primary" />
<TextView
android:id="@+id/tvTransactionDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="@color/text_secondary"
android:layout_marginTop="4dp" />
<TextView
android:id="@+id/tvTransactionCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="@color/primary"
android:background="@drawable/category_background"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:layout_marginTop="8dp" />
</LinearLayout>
<!-- Valor da transação -->
<TextView
android:id="@+id/tvTransactionAmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -1,5 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<!-- Cores do FinZen -->
<color name="primary">#2196F3</color>
<color name="primary_dark">#1976D2</color>
<color name="accent">#03DAC6</color>
<color name="text_primary">#212121</color>
<color name="text_secondary">#757575</color>
<color name="background">#F5F5F5</color>
<color name="error">#F44336</color>
<color name="success">#4CAF50</color>
</resources> </resources>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Tema base do app -->
<style android:name="Theme.Finase" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Cores principais -->
<item android:name="colorPrimary">@color/primary</item>
<item android:name="colorPrimaryVariant">@color/primary_dark</item>
<item android:name="colorOnPrimary">@color/white</item>
<!-- Cores secundárias -->
<item android:name="colorSecondary">@color/accent</item>
<item android:name="colorSecondaryVariant">@color/accent</item>
<item android:name="colorOnSecondary">@color/black</item>
<!-- Cor da status bar -->
<item android:name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Cor da navigation bar (opcional) -->
<item android:name="android:navigationBarColor">@color/white</item>
<!-- Estilo dos botões -->
<item android:name="materialButtonStyle">@style/Widget.Finase.Button</item>
</style>
<!-- Estilo para botões -->
<style android:name="Widget.Finase.Button" parent="Widget.MaterialComponents.Button">
<item android:name="android:minHeight">48dp</item>
<item android:name="android:insetTop">0dp</item>
<item android:name="android:insetBottom">0dp</item>
<item android:name="cornerRadius">24dp</item>
</style>
<!-- Estilo para TextViews -->
<style android:name="Widget.Finase.TextView" parent="Widget.AppCompat.TextView">
<item android:name="android:textColor">@color/text_primary</item>
</style>
<!-- Estilo para EditText -->
<style android:name="Widget.Finase.EditText" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<item android:name="boxStrokeColor">@color/gray_light</item>
<item android:name="hintTextColor">@color/text_secondary</item>
</style>
</resources>