Compare commits

...

43 Commits

Author SHA1 Message Date
894c9a845c adicao de jogadores na app 2026-02-26 09:58:16 +00:00
337440eb91 alteracoes precisas na app 2026-02-24 17:17:47 +00:00
421ba7c2e2 correcao de erros 2026-02-03 16:48:28 +00:00
2087572fa9 correcao de erros 2026-02-03 16:33:41 +00:00
e797216506 mudancas design 2026-01-29 10:37:46 +00:00
695e8cac2e imagem dos clubes inseridas 2026-01-29 10:30:59 +00:00
beede716c6 mudanca design 2026-01-28 10:09:22 +00:00
e2c3d0badd mudancas no design 2026-01-28 10:06:56 +00:00
7e70721c6c tirei um botao que nao serve para nada 2026-01-28 10:03:08 +00:00
e1150b3bf0 mudança ecra de clubes 2026-01-28 09:58:04 +00:00
e7aa23bbec mudanca de logo 2026-01-28 09:25:25 +00:00
2d27e4a227 mudanca logo 2026-01-28 09:20:09 +00:00
24acb90d58 mudanca de logo 2026-01-28 08:58:12 +00:00
371a298636 Correção da lista de clubes e jogadores 2026-01-27 17:12:17 +00:00
cd527224bf correcao 2026-01-23 16:36:17 +00:00
214d51d36e correcao 2026-01-23 16:29:12 +00:00
750e91538c mudancas para por a base de dados das equipas 2026-01-23 16:23:06 +00:00
f034364a41 alteracoes 2026-01-21 10:39:29 +00:00
a70395f258 mudanca visual 2026-01-20 17:11:20 +00:00
1dbbcb9a78 mudanca n visual 2026-01-20 17:08:19 +00:00
47a436c97d alteracoes design 2026-01-20 17:01:20 +00:00
66746a459a mudancas de visual 2026-01-20 16:57:44 +00:00
e06b4be7bf correcao de erros 2026-01-20 16:49:43 +00:00
6618e27afe alteracoes design de login e criar conta 2026-01-20 16:41:03 +00:00
ae62000ff3 refactor: Update settings UI to use color resources and refine MaterialCardView styling. 2026-01-20 15:49:42 +00:00
62d2a6bb51 mudanca de visual 2026-01-20 15:40:14 +00:00
fc4f786739 mudanças visual do app 2026-01-20 15:36:49 +00:00
ca26b8e146 correcao de erros 2026-01-20 14:57:35 +00:00
b297ff0e6e ver jogos ao vivo e ver os clubes 2026-01-20 14:53:21 +00:00
2e47ced7c7 alteraçoes 2025-12-12 10:40:22 +00:00
fe0dbed813 testessssss 2025-12-12 10:08:59 +00:00
f2ece221b6 teste 2025-12-12 10:07:25 +00:00
743ddeb3db mudanças 2025-12-12 09:28:14 +00:00
85a1907ef8 mudanças 2025-12-12 09:27:49 +00:00
2d4d229eac mudanças 2025-12-12 09:27:25 +00:00
4b766067f4 melhoramento da app 2025-12-06 22:26:42 +00:00
460b719785 adicao de botao de terminar sessao 2025-12-06 22:04:01 +00:00
81eb71bd46 Atualizar LoginActivity e ContaActivity 2025-12-06 21:47:50 +00:00
49ba834e96 correcao de coisas 2025-12-06 21:29:38 +00:00
4d80a9a27d correcao de erros 2025-12-06 21:13:22 +00:00
9875c82e65 correçao de erros no ecra da conta 2025-12-06 20:50:17 +00:00
66d019d9b6 Atualização das telas de login e conta + melhorias de layout 2025-12-05 00:05:43 +00:00
57056bbd6e correção de erros 2025-12-04 23:43:51 +00:00
100 changed files with 4483 additions and 519 deletions

View File

@@ -4,14 +4,6 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-11-26T09:17:18.598825Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="LocalEmulator" identifier="path=/Users/230421/.android/avd/Medium_Phone.avd" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState> </SelectionState>
</selectionStates> </selectionStates>
</component> </component>

7
.idea/misc.xml generated
View File

@@ -6,4 +6,11 @@
<component name="ProjectType"> <component name="ProjectType">
<option name="id" value="Android" /> <option name="id" value="Android" />
</component> </component>
<component name="VisualizationToolProject">
<option name="state">
<ProjectState>
<option name="scale" value="0.2492626953125" />
</ProjectState>
</option>
</component>
</project> </project>

View File

@@ -46,6 +46,7 @@ dependencies {
implementation(libs.credentials.play.services.auth) implementation(libs.credentials.play.services.auth)
implementation(libs.googleid) implementation(libs.googleid)
implementation(libs.firebase.database) implementation(libs.firebase.database)
implementation(libs.firebase.storage)
implementation(libs.lifecycle.livedata.ktx) implementation(libs.lifecycle.livedata.ktx)
implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.viewmodel.ktx)
implementation(libs.navigation.fragment) implementation(libs.navigation.fragment)
@@ -53,4 +54,5 @@ dependencies {
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core) androidTestImplementation(libs.espresso.core)
implementation("com.github.bumptech.glide:glide:4.16.0")
} }

View File

@@ -1,6 +1,7 @@
{ {
"project_info": { "project_info": {
"project_number": "89853204936", "project_number": "89853204936",
"firebase_url": "https://vdcscore-default-rtdb.firebaseio.com",
"project_id": "vdcscore", "project_id": "vdcscore",
"storage_bucket": "vdcscore.firebasestorage.app" "storage_bucket": "vdcscore.firebasestorage.app"
}, },

View File

@@ -2,6 +2,11 @@
<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"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.CAMERA" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"

View File

@@ -30,12 +30,13 @@ public class CriarContaActivity extends AppCompatActivity {
}); });
TextInputEditText editPassword2; TextInputEditText editPassword2;
TextInputEditText editEmail; TextInputEditText editEmail;
TextInputEditText editUserName;
TextInputEditText editConfirmPassword; TextInputEditText editConfirmPassword;
Button btnCreateAccount; Button btnCreateAccount;
TextView txtGoLogin; TextView txtGoLogin;
editEmail = findViewById(R.id.editEmail); editEmail = findViewById(R.id.editEmail);
editUserName = findViewById(R.id.editUserName);
editPassword2 = findViewById(R.id.editPassword2); editPassword2 = findViewById(R.id.editPassword2);
editConfirmPassword = findViewById(R.id.editConfirmPassword); editConfirmPassword = findViewById(R.id.editConfirmPassword);
btnCreateAccount = findViewById(R.id.btnCreateAccount); btnCreateAccount = findViewById(R.id.btnCreateAccount);
@@ -45,11 +46,12 @@ public class CriarContaActivity extends AppCompatActivity {
btnCreateAccount.setOnClickListener(new View.OnClickListener() { btnCreateAccount.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
String email = editEmail.getText().toString(); String email = editEmail.getText().toString().trim();
String pass = editPassword2.getText().toString(); String userName = editUserName.getText().toString().trim();
String conf = editConfirmPassword.getText().toString(); String pass = editPassword2.getText().toString().trim();
String conf = editConfirmPassword.getText().toString().trim();
if (email.isEmpty() || pass.isEmpty() || conf.isEmpty()) { if (email.isEmpty() || userName.isEmpty() || pass.isEmpty() || conf.isEmpty()) {
Toast.makeText(CriarContaActivity.this, "Preencha todos os campos!", Toast.LENGTH_SHORT).show(); Toast.makeText(CriarContaActivity.this, "Preencha todos os campos!", Toast.LENGTH_SHORT).show();
return; return;
} }
@@ -60,14 +62,32 @@ public class CriarContaActivity extends AppCompatActivity {
} }
FirebaseAuth auth = FirebaseAuth.getInstance(); FirebaseAuth auth = FirebaseAuth.getInstance();
auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this, task -> { auth.createUserWithEmailAndPassword(email, pass).addOnCompleteListener(CriarContaActivity.this,
task -> {
if (task.isSuccessful()) { if (task.isSuccessful()) {
// Atualizar nome de utilizador
com.google.firebase.auth.FirebaseUser user = auth.getCurrentUser();
if (user != null) {
com.google.firebase.auth.UserProfileChangeRequest profileUpdates = new com.google.firebase.auth.UserProfileChangeRequest.Builder()
.setDisplayName(userName)
.build();
Intent intent= new Intent(CriarContaActivity.this, MainActivity.class); user.updateProfile(profileUpdates).addOnCompleteListener(updateTask -> {
Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
startActivity(intent); startActivity(intent);
finish(); finish();
});
} else { } else {
Toast.makeText(CriarContaActivity.this, "Erro ao criar conta!", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(CriarContaActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
} else {
String errorMessage = "Erro ao criar conta!";
if (task.getException() != null && task.getException().getMessage() != null) {
errorMessage = "Erro: " + task.getException().getMessage();
}
Toast.makeText(CriarContaActivity.this, errorMessage, Toast.LENGTH_LONG).show();
} }
}); });

View File

@@ -1,8 +1,10 @@
package com.example.vdcscore; package com.example.vdcscore;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@@ -15,11 +17,17 @@ public class LoginActivity extends AppCompatActivity {
TextInputEditText editEmail, editPassword; TextInputEditText editEmail, editPassword;
Button btnLogin; Button btnLogin;
CheckBox checkRememberMe;
FirebaseAuth mAuth; FirebaseAuth mAuth;
private TextView criarContaTextView; private TextView criarContaTextView;
private TextView txtForgotPassword; private TextView txtForgotPassword;
private static final String PREFS_NAME = "LoginPrefs";
private static final String KEY_EMAIL = "email";
private static final String KEY_PASSWORD = "password";
private static final String KEY_REMEMBER = "remember";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -28,6 +36,7 @@ public class LoginActivity extends AppCompatActivity {
editEmail = findViewById(R.id.editEmail); editEmail = findViewById(R.id.editEmail);
editPassword = findViewById(R.id.editPassword2); editPassword = findViewById(R.id.editPassword2);
btnLogin = findViewById(R.id.btnLogin); btnLogin = findViewById(R.id.btnLogin);
checkRememberMe = findViewById(R.id.checkRememberMe);
criarContaTextView = findViewById(R.id.txtRegister); criarContaTextView = findViewById(R.id.txtRegister);
txtForgotPassword = findViewById(R.id.txtForgotPassword); txtForgotPassword = findViewById(R.id.txtForgotPassword);
@@ -36,6 +45,45 @@ public class LoginActivity extends AppCompatActivity {
btnLogin.setOnClickListener(v -> loginUser()); btnLogin.setOnClickListener(v -> loginUser());
criarContaTextView.setOnClickListener(view -> criarConta()); criarContaTextView.setOnClickListener(view -> criarConta());
txtForgotPassword.setOnClickListener(view -> recuperarPassword()); txtForgotPassword.setOnClickListener(view -> recuperarPassword());
// Carregar credenciais guardadas
loadSavedCredentials();
}
private void loadSavedCredentials() {
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
boolean remember = prefs.getBoolean(KEY_REMEMBER, false);
if (remember) {
String savedEmail = prefs.getString(KEY_EMAIL, "");
String savedPassword = prefs.getString(KEY_PASSWORD, "");
if (!savedEmail.isEmpty() && !savedPassword.isEmpty()) {
editEmail.setText(savedEmail);
editPassword.setText(savedPassword);
checkRememberMe.setChecked(true);
// Tentar login automático
autoLogin(savedEmail, savedPassword);
}
}
}
private void autoLogin(String email, String password) {
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
// Login automático bem-sucedido
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
} else {
// Se o login automático falhar, apenas limpar a password do campo
// O utilizador pode tentar fazer login manualmente
editPassword.setText("");
}
});
} }
private void criarConta() { private void criarConta() {
@@ -60,27 +108,56 @@ public class LoginActivity extends AppCompatActivity {
mAuth.signInWithEmailAndPassword(email, password) mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(task -> { .addOnCompleteListener(task -> {
if (task.isSuccessful()) { if (task.isSuccessful()) {
// Guardar credenciais se "Lembrar-me" estiver marcado
if (checkRememberMe.isChecked()) {
saveCredentials(email, password);
} else {
clearSavedCredentials();
}
Toast.makeText(this, "Login efetuado!", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Login efetuado!", Toast.LENGTH_SHORT).show();
// Abre a tua página principal // Abre a tua página principal
startActivity(new Intent(LoginActivity.this, MainActivity.class)); Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish(); finish();
} else { } else {
Toast.makeText(this, String errorMessage = "Erro ao fazer login!";
"Erro: " + task.getException().getMessage(), if (task.getException() != null && task.getException().getMessage() != null) {
Toast.LENGTH_LONG).show(); errorMessage = "Erro: " + task.getException().getMessage();
}
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
} }
}); });
} }
private void saveCredentials(String email, String password) {
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(KEY_EMAIL, email);
editor.putString(KEY_PASSWORD, password);
editor.putBoolean(KEY_REMEMBER, true);
editor.apply();
}
private void clearSavedCredentials() {
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.apply();
}
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
// Verificar se já está autenticado (caso o login automático não tenha funcionado)
if (FirebaseAuth.getInstance().getCurrentUser() != null){ if (FirebaseAuth.getInstance().getCurrentUser() != null){
Intent intent = new Intent(LoginActivity.this, MainActivity.class); Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent); startActivity(intent);
finish();
} }
} }
} }

View File

@@ -1,8 +1,12 @@
package com.example.vdcscore; package com.example.vdcscore;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.Menu; import android.view.Menu;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
@@ -15,45 +19,203 @@ import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import com.example.vdcscore.databinding.ActivityMainBinding; import com.example.vdcscore.databinding.ActivityMainBinding;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import java.io.InputStream;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.text.InputType;
import android.widget.EditText;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import com.google.firebase.auth.UserProfileChangeRequest;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration; private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding; private ActivityMainBinding binding;
private ActivityResultLauncher<String> mGetContent;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// Carregar preferência do Dark Mode
android.content.SharedPreferences prefs = getSharedPreferences("SettingsPrefs",
android.content.Context.MODE_PRIVATE);
boolean isDarkMode = prefs.getBoolean("dark_mode", false);
if (isDarkMode) {
androidx.appcompat.app.AppCompatDelegate
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES);
} else {
androidx.appcompat.app.AppCompatDelegate
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO);
}
binding = ActivityMainBinding.inflate(getLayoutInflater()); binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); setContentView(binding.getRoot());
setSupportActionBar(binding.appBarMain.toolbar); setSupportActionBar(binding.appBarMain.toolbar);
binding.appBarMain.fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null)
.setAnchorView(R.id.fab).show();
}
});
DrawerLayout drawer = binding.drawerLayout; DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView; NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each // Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations. // menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder( mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_definicoes) R.id.nav_home, R.id.nav_gallery, R.id.nav_definicoes,
R.id.nav_live_games, R.id.nav_clubs)
.setOpenableLayout(drawer) .setOpenableLayout(drawer)
.build(); .build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration); NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController); NavigationUI.setupWithNavController(navigationView, navController);
// Initialize Gallery Launcher
mGetContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
uri -> {
if (uri != null) {
uploadImageToStorage(uri);
}
});
// Carregar dados do utilizador no menu lateral
loadUserDataInNavHeader();
}
private void loadUserDataInNavHeader() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null)
return;
View headerView = binding.navView.getHeaderView(0);
TextView textViewName = headerView.findViewById(R.id.textViewName);
ImageView imageView = headerView.findViewById(R.id.imageView);
// Carregar nome
if (textViewName != null) {
if (user.getDisplayName() != null && !user.getDisplayName().isEmpty()) {
textViewName.setText(user.getDisplayName());
} else {
textViewName.setText("Utilizador");
}
}
// Carregar foto de perfil
if (imageView != null) {
imageView.setOnClickListener(v -> showChangeProfilePhotoDialog());
if (user.getPhotoUrl() != null) {
loadProfileImageInNavHeader(user.getPhotoUrl().toString(), imageView);
} else {
// Tentar carregar do Storage
loadProfileImageFromStorage(imageView);
}
}
}
private void loadProfileImageInNavHeader(String imageUrl, ImageView imageView) {
new Thread(() -> {
InputStream input = null;
try {
java.net.URL url = new java.net.URL(imageUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
runOnUiThread(() -> {
if (bitmap != null && imageView != null) {
imageView.setImageBitmap(bitmap);
imageView.setScaleType(android.widget.ImageView.ScaleType.CENTER_CROP);
}
});
} catch (Exception e) {
// Se falhar, tentar carregar do Storage
runOnUiThread(() -> loadProfileImageFromStorage(imageView));
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
// Ignorar erro ao fechar
}
}
}
}).start();
}
private void loadProfileImageFromStorage(ImageView imageView) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null || imageView == null)
return;
com.google.firebase.storage.FirebaseStorage.getInstance()
.getReference()
.child("profile_images/" + user.getUid() + ".jpg")
.getDownloadUrl()
.addOnSuccessListener(uri -> {
loadProfileImageInNavHeader(uri.toString(), imageView);
})
.addOnFailureListener(e -> {
// Manter imagem padrão
});
}
private void showChangeProfilePhotoDialog() {
mGetContent.launch("image/*");
}
private void uploadImageToStorage(Uri imageUri) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null)
return;
StorageReference storageRef = com.google.firebase.storage.FirebaseStorage.getInstance().getReference();
StorageReference profileRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
Toast.makeText(this, "A carregar imagem...", Toast.LENGTH_SHORT).show();
profileRef.putFile(imageUri)
.addOnSuccessListener(taskSnapshot -> {
profileRef.getDownloadUrl().addOnSuccessListener(uri -> {
updateUserProfile(uri);
});
})
.addOnFailureListener(e -> {
Toast.makeText(MainActivity.this, "Erro ao carregar imagem: " + e.getMessage(), Toast.LENGTH_SHORT)
.show();
});
}
private void updateUserProfile(Uri photoUri) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null)
return;
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setPhotoUri(photoUri)
.build();
user.updateProfile(profileUpdates)
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Toast.makeText(MainActivity.this, "Foto de perfil atualizada!", Toast.LENGTH_SHORT).show();
loadUserDataInNavHeader(); // Refresh UI
} else {
Toast.makeText(MainActivity.this, "Erro ao atualizar perfil.", Toast.LENGTH_SHORT).show();
}
});
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present. // Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.main, menu); // getMenuInflater().inflate(R.menu.main, menu);
return false; return false;
} }
@@ -63,4 +225,11 @@ public class MainActivity extends AppCompatActivity {
return NavigationUI.navigateUp(navController, mAppBarConfiguration) return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp(); || super.onSupportNavigateUp();
} }
@Override
protected void onResume() {
super.onResume();
// Atualizar dados do utilizador quando voltar à activity
loadUserDataInNavHeader();
}
} }

View File

@@ -59,9 +59,11 @@ public class RecuperarPasswordActivity extends AppCompatActivity {
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
voltarLogin(); voltarLogin();
} else { } else {
Toast.makeText(this, String errorMessage = "Erro ao enviar email de recuperação!";
"Erro: " + task.getException().getMessage(), if (task.getException() != null && task.getException().getMessage() != null) {
Toast.LENGTH_LONG).show(); errorMessage = "Erro: " + task.getException().getMessage();
}
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
} }
}); });
} }

View File

@@ -0,0 +1,104 @@
package com.example.vdcscore.data;
import androidx.annotation.NonNull;
import com.example.vdcscore.models.Club;
import com.example.vdcscore.models.Jornada;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class FirebaseRepository {
private final DatabaseReference mDatabase;
private static FirebaseRepository instance;
private FirebaseRepository() {
mDatabase = FirebaseDatabase.getInstance().getReference();
}
public static synchronized FirebaseRepository getInstance() {
if (instance == null) {
instance = new FirebaseRepository();
}
return instance;
}
// --- Clubs ---
public void addClub(Club club, OnCompleteListener<Void> onCompleteListener) {
String key = String.valueOf(club.getId());
if (key == null || key.isEmpty()) {
key = mDatabase.child("clubs").push().getKey();
club.setId(Integer.parseInt(key));
}
mDatabase.child("clubs").child(key).setValue(club).addOnCompleteListener(onCompleteListener);
}
public void getClubs(final DataCallback<List<Club>> callback) {
mDatabase.child("clubs").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
List<Club> clubs = new ArrayList<>();
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
Club club = postSnapshot.getValue(Club.class);
if (club != null) {
club.setId(Integer.parseInt(postSnapshot.getKey()));
clubs.add(club);
}
}
callback.onSuccess(clubs);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
callback.onFailure(error.toException());
}
});
}
// --- Jornadas ---
public void addJornada(Jornada jornada, OnCompleteListener<Void> onCompleteListener) {
String key = jornada.getId();
if (key == null || key.isEmpty()) {
key = mDatabase.child("jornadas").push().getKey();
jornada.setId(key);
}
mDatabase.child("jornadas").child(key).setValue(jornada).addOnCompleteListener(onCompleteListener);
}
public void getJornadas(final DataCallback<List<Jornada>> callback) {
mDatabase.child("jornadas").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
List<Jornada> jornadas = new ArrayList<>();
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
Jornada jornada = postSnapshot.getValue(Jornada.class);
if (jornada != null) {
jornada.setId(postSnapshot.getKey());
jornadas.add(jornada);
}
}
callback.onSuccess(jornadas);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
callback.onFailure(error.toException());
}
});
}
public interface DataCallback<T> {
void onSuccess(T data);
void onFailure(Exception e);
}
}

View File

@@ -0,0 +1,136 @@
package com.example.vdcscore.models;
import com.google.firebase.database.PropertyName;
import java.util.ArrayList;
import java.io.Serializable;
import java.util.List;
public class Club implements Serializable {
@PropertyName("id")
private int id;
@PropertyName("nome")
private String name;
@PropertyName("imagem")
private String imageUrl;
@PropertyName("campo")
private String stadium;
@PropertyName("ano fundacao")
private int foundationYear;
@PropertyName("morada")
private String address;
@PropertyName("presidente")
private String president;
@PropertyName("jogadores")
private ArrayList<Player> players;
public Club() {
// Default constructor for Firebase
players = new ArrayList<>();
}
public Club(int id, String name, String imageUrl, String stadium, int foundationYear, String address,
String president) {
this.id = id;
this.name = name;
this.imageUrl = imageUrl;
this.stadium = stadium;
this.foundationYear = foundationYear;
this.address = address;
this.president = president;
this.players = new ArrayList<>();
}
@PropertyName("id")
public int getId() {
return id;
}
@PropertyName("id")
public void setId(int id) {
this.id = id;
}
@PropertyName("nome")
public String getName() {
return name;
}
@PropertyName("nome")
public void setName(String name) {
this.name = name;
}
@PropertyName("imagem")
public String getImageUrl() {
return imageUrl;
}
@PropertyName("imagem")
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
@PropertyName("campo")
public String getStadium() {
return stadium;
}
@PropertyName("campo")
public void setStadium(String stadium) {
this.stadium = stadium;
}
@PropertyName("ano fundacao")
public int getFoundationYear() {
return foundationYear;
}
@PropertyName("ano fundacao")
public void setFoundationYear(int foundationYear) {
this.foundationYear = foundationYear;
}
@PropertyName("morada")
public String getAddress() {
return address;
}
@PropertyName("morada")
public void setAddress(String address) {
this.address = address;
}
@PropertyName("presidente")
public String getPresident() {
return president;
}
@PropertyName("presidente")
public void setPresident(String president) {
this.president = president;
}
@PropertyName("jogadores")
public ArrayList<Player> getPlayersMap() {
return players;
}
@PropertyName("jogadores")
public void setPlayersMap(ArrayList<Player> players) {
this.players = players;
}
public List<Player> getPlayersList() {
if (players == null)
return new ArrayList<>();
return new ArrayList<>(players);
}
}

View File

@@ -0,0 +1,102 @@
package com.example.vdcscore.models;
public class Game {
private String id;
private String homeTeamId;
private String awayTeamId;
private String homeTeamName;
private String awayTeamName;
private int homeScore;
private int awayScore;
private boolean isFinished;
private long timestamp;
public Game() {
// Required for Firebase
}
public Game(String id, String homeTeamId, String awayTeamId, String homeTeamName, String awayTeamName,
long timestamp) {
this.id = id;
this.homeTeamId = homeTeamId;
this.awayTeamId = awayTeamId;
this.homeTeamName = homeTeamName;
this.awayTeamName = awayTeamName;
this.timestamp = timestamp;
this.isFinished = false;
this.homeScore = 0;
this.awayScore = 0;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHomeTeamId() {
return homeTeamId;
}
public void setHomeTeamId(String homeTeamId) {
this.homeTeamId = homeTeamId;
}
public String getAwayTeamId() {
return awayTeamId;
}
public void setAwayTeamId(String awayTeamId) {
this.awayTeamId = awayTeamId;
}
public String getHomeTeamName() {
return homeTeamName;
}
public void setHomeTeamName(String homeTeamName) {
this.homeTeamName = homeTeamName;
}
public String getAwayTeamName() {
return awayTeamName;
}
public void setAwayTeamName(String awayTeamName) {
this.awayTeamName = awayTeamName;
}
public int getHomeScore() {
return homeScore;
}
public void setHomeScore(int homeScore) {
this.homeScore = homeScore;
}
public int getAwayScore() {
return awayScore;
}
public void setAwayScore(int awayScore) {
this.awayScore = awayScore;
}
public boolean isFinished() {
return isFinished;
}
public void setFinished(boolean finished) {
isFinished = finished;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}

View File

@@ -0,0 +1,55 @@
package com.example.vdcscore.models;
import java.util.ArrayList;
import java.util.List;
public class Jornada {
private String id;
private int number;
private List<Game> games;
private boolean isCurrent;
public Jornada() {
// Required for Firebase
this.games = new ArrayList<>();
}
public Jornada(String id, int number) {
this.id = id;
this.number = number;
this.games = new ArrayList<>();
this.isCurrent = false;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public List<Game> getGames() {
return games;
}
public void setGames(List<Game> games) {
this.games = games;
}
public boolean isCurrent() {
return isCurrent;
}
public void setCurrent(boolean current) {
isCurrent = current;
}
}

View File

@@ -0,0 +1,40 @@
package com.example.vdcscore.models;
import com.google.firebase.database.PropertyName;
public class Player {
@PropertyName("id")
private int id;
@PropertyName("nome")
private String nome;
public Player() {
// Default constructor required for calls to DataSnapshot.getValue(Player.class)
}
public Player(int id, String nome) {
this.id = id;
this.nome = nome;
}
@PropertyName("id")
public int getId() {
return id;
}
@PropertyName("id")
public void setId(int id) {
this.id = id;
}
@PropertyName("nome")
public String getNome() {
return nome;
}
@PropertyName("nome")
public void setNome(String nome) {
this.nome = nome;
}
}

View File

@@ -0,0 +1,74 @@
package com.example.vdcscore.ui.clubs;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.vdcscore.R;
import com.example.vdcscore.models.Club;
import java.util.List;
public class ClubAdapter extends RecyclerView.Adapter<ClubAdapter.ClubViewHolder> {
private final List<Club> mClubs;
private final OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(Club club);
}
public ClubAdapter(List<Club> clubs, OnItemClickListener listener) {
mClubs = clubs;
mListener = listener;
}
@NonNull
@Override
public ClubViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_club, parent, false);
return new ClubViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ClubViewHolder holder, int position) {
Club club = mClubs.get(position);
holder.bind(club, mListener);
}
@Override
public int getItemCount() {
return mClubs.size();
}
static class ClubViewHolder extends RecyclerView.ViewHolder {
private final TextView name;
private final TextView stadium;
private final ImageView image_detail_logo;
public ClubViewHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.text_club_name);
stadium = itemView.findViewById(R.id.text_club_stadium);
image_detail_logo = itemView.findViewById(R.id.image_club_logo);
}
public void bind(final Club club, final OnItemClickListener listener) {
name.setText(club.getName());
stadium.setText(club.getStadium());
Glide.with(itemView.getContext())
.load(club.getImageUrl())
.into(image_detail_logo);
itemView.setOnClickListener(v -> listener.onItemClick(club));
}
}
}

View File

@@ -0,0 +1,125 @@
package com.example.vdcscore.ui.clubs;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.example.vdcscore.R;
import com.example.vdcscore.databinding.FragmentClubDetailBinding;
import com.example.vdcscore.models.Club;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.bumptech.glide.Glide;
public class ClubDetailFragment extends Fragment {
private FragmentClubDetailBinding binding;
private DatabaseReference mDatabase;
private String clubId;
private String escalao;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
clubId = getArguments().getString("clubId");
escalao = getArguments().getString("escalao");
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentClubDetailBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getArguments() != null) {
Club clubeRecebido = (Club) getArguments().getSerializable("clube_selecionado");
if (clubeRecebido != null) {
// Preencher views diretamente
binding.textDetailClubName.setText(clubeRecebido.getName());
binding.textDetailFoundation.setText(String.valueOf(clubeRecebido.getFoundationYear()));
binding.textDetailPresident.setText(clubeRecebido.getPresident());
binding.textDetailAddress.setText(clubeRecebido.getAddress());
if (getContext() != null) {
Glide.with(this)
.load(clubeRecebido.getImageUrl())
.placeholder(R.mipmap.ic_launcher_round)
.error(R.mipmap.ic_launcher)
.into(binding.imageDetailLogo);
}
// Configurar o botão para ver jogadores
binding.btnPlayers.setOnClickListener(v -> {
Bundle bundle = new Bundle();
// Passar o 'clube_selecionado' também para a lista de jogadores se necessário,
// ou passar o ID como antes se o fragmento de jogadores esperar ID
bundle.putString("clubId", String.valueOf(clubeRecebido.getId()));
bundle.putString("escalao", escalao);
// Se o ClubPlayersFragment esperar "clube_selecionado" tambem, poderiamos
// passar:
// bundle.putSerializable("clube_selecionado", clubeRecebido);
Navigation.findNavController(view).navigate(R.id.action_nav_club_detail_to_nav_club_players,
bundle);
});
}
}
}
private void loadClubDetails() {
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
Club club = snapshot.getValue(Club.class);
if (club != null) {
binding.textDetailClubName.setText(club.getName());
binding.textDetailFoundation.setText(String.valueOf(club.getFoundationYear()));
binding.textDetailPresident.setText(club.getPresident());
binding.textDetailAddress.setText(club.getAddress());
// binding.textDetailStadium.setText(club.getStadium()); // Hidden for now
// binding.imageDetailLogo.setImageResource(R.mipmap.ic_launcher_round);
if (getContext() != null) {
Glide.with(ClubDetailFragment.this)
.load(club.getImageUrl())
.placeholder(R.mipmap.ic_launcher_round)
.error(R.mipmap.ic_launcher)
.into(binding.imageDetailLogo);
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
if (getContext() != null) {
Toast.makeText(getContext(), "Failed to load club details.", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@@ -0,0 +1,103 @@
package com.example.vdcscore.ui.clubs;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.example.vdcscore.databinding.FragmentClubPlayersBinding;
import com.example.vdcscore.models.Club;
import com.example.vdcscore.models.Player;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class ClubPlayersFragment extends Fragment {
private FragmentClubPlayersBinding binding;
private DatabaseReference mDatabase;
private String clubId;
private String escalao;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
clubId = getArguments().getString("clubId");
escalao = getArguments().getString("escalao");
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
binding = FragmentClubPlayersBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.recyclerPlayersList.setLayoutManager(new LinearLayoutManager(getContext()));
binding.progressBarPlayers.setVisibility(View.VISIBLE);
if (clubId != null && escalao != null) {
mDatabase = FirebaseDatabase.getInstance().getReference().child("clubes").child(escalao).child(clubId);
loadPlayers();
} else {
binding.progressBarPlayers.setVisibility(View.GONE);
binding.textNoPlayers.setVisibility(View.VISIBLE);
binding.textNoPlayers.setText("Erro: Clube ou escalão não identificado.");
}
}
private void loadPlayers() {
mDatabase.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
Club club = snapshot.getValue(Club.class);
binding.progressBarPlayers.setVisibility(View.GONE);
if (club != null) {
List<Player> playerList = club.getPlayersList();
if (playerList != null && !playerList.isEmpty()) {
PlayerAdapter adapter = new PlayerAdapter(playerList);
binding.recyclerPlayersList.setAdapter(adapter);
binding.textNoPlayers.setVisibility(View.GONE);
} else {
binding.textNoPlayers.setVisibility(View.VISIBLE);
}
} else {
binding.textNoPlayers.setVisibility(View.VISIBLE);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
if (getContext() != null) {
Toast.makeText(getContext(), "Failed to load players.", Toast.LENGTH_SHORT).show();
}
binding.progressBarPlayers.setVisibility(View.GONE);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@@ -0,0 +1,122 @@
package com.example.vdcscore.ui.clubs;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.vdcscore.R;
import com.example.vdcscore.databinding.FragmentClubsBinding;
import com.example.vdcscore.models.Club;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class ClubsFragment extends Fragment {
private FragmentClubsBinding binding;
private DatabaseReference mDatabase;
private ValueEventListener mValueEventListener;
private static final String TAG = "ClubsFragment";
private String currentEscalao = "seniores"; // Default selection
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
binding = FragmentClubsBinding.inflate(inflater, container, false);
View root = binding.getRoot();
RecyclerView recyclerView = binding.recyclerClubs;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
ProgressBar progressBar = binding.progressBar;
// Set up toggle listener
binding.toggleGroupEscalao.addOnButtonCheckedListener((group, checkedId, isChecked) -> {
if (isChecked) {
if (checkedId == R.id.btnJuniores) {
currentEscalao = "juniores";
} else if (checkedId == R.id.btnSeniores) {
currentEscalao = "seniores";
}
loadClubsData(recyclerView, progressBar);
}
});
// Initial Data Load
loadClubsData(recyclerView, progressBar);
return root;
}
private void loadClubsData(RecyclerView recyclerView, ProgressBar progressBar) {
progressBar.setVisibility(View.VISIBLE);
mDatabase = FirebaseDatabase.getInstance().getReference().child("clubes").child(currentEscalao);
// Remove previous listener to avoid duplicate data or leaks
if (mValueEventListener != null) {
mDatabase.removeEventListener(mValueEventListener);
}
mValueEventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
List<Club> clubs = new ArrayList<>();
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
Club club = postSnapshot.getValue(Club.class);
if (club != null) {
clubs.add(club);
}
}
ClubAdapter adapter = new ClubAdapter(clubs, club -> {
Bundle bundle = new Bundle();
bundle.putSerializable("clube_selecionado", club);
bundle.putString("escalao", currentEscalao);
androidx.navigation.fragment.NavHostFragment.findNavController(ClubsFragment.this)
.navigate(R.id.action_nav_clubs_to_nav_club_detail, bundle);
});
recyclerView.setAdapter(adapter);
progressBar.setVisibility(View.GONE);
if (clubs.isEmpty()) {
// Keep UI empty but don't show mock data automatically to avoid confusion
// Toast.makeText(getContext(), "No clubs found.", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.w(TAG, "loadClubs:onCancelled", error.toException());
if (getContext() != null) {
Toast.makeText(getContext(), "Failed to load clubs.", Toast.LENGTH_SHORT).show();
}
if (binding != null) {
binding.progressBar.setVisibility(View.GONE);
}
}
};
mDatabase.addValueEventListener(mValueEventListener);
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mDatabase != null && mValueEventListener != null) {
mDatabase.removeEventListener(mValueEventListener);
}
binding = null;
}
}

View File

@@ -0,0 +1,57 @@
package com.example.vdcscore.ui.clubs;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.vdcscore.R;
import com.example.vdcscore.models.Player;
import java.util.List;
public class PlayerAdapter extends RecyclerView.Adapter<PlayerAdapter.PlayerViewHolder> {
private final List<Player> mPlayers;
public PlayerAdapter(List<Player> players) {
mPlayers = players;
}
@NonNull
@Override
public PlayerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_player, parent, false);
return new PlayerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull PlayerViewHolder holder, int position) {
Player player = mPlayers.get(position);
holder.bind(player);
}
@Override
public int getItemCount() {
return mPlayers.size();
}
static class PlayerViewHolder extends RecyclerView.ViewHolder {
private final TextView name;
public PlayerViewHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.text_player_name);
}
public void bind(Player player) {
if (player != null){
name.setText(player.getNome());
}
}
}
}

View File

@@ -1,26 +1,491 @@
package com.example.vdcscore.ui.definicoes; package com.example.vdcscore.ui.definicoes;
import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
import com.example.vdcscore.LoginActivity;
import com.example.vdcscore.R; import com.example.vdcscore.R;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.textfield.TextInputEditText;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.UserProfileChangeRequest;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class ContaActivity extends AppCompatActivity { public class ContaActivity extends AppCompatActivity {
private ImageView imageProfile;
private TextInputEditText editName;
private TextView textEmail;
private Button btnSaveAll;
private Button btnChangeEmail;
private Button btnChangePassword;
private Button btnLogout;
private View btnChangePhoto;
private View cardImageContainer;
private FirebaseAuth mAuth;
private FirebaseStorage mStorage;
private StorageReference storageRef;
private ProgressDialog progressDialog;
private ActivityResultLauncher<Intent> imagePickerLauncher;
private ActivityResultLauncher<String> permissionLauncher;
private Uri selectedImageUri;
private static final String PREFS_NAME = "LoginPrefs";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
EdgeToEdge.enable(this); EdgeToEdge.enable(this);
setContentView(R.layout.activity_conta); setContentView(R.layout.activity_conta);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets; return insets;
}); });
// Inicializar componentes
initViews();
initFirebase();
setupImagePicker();
setupPermissionLauncher();
loadUserData();
setupListeners();
}
private void initViews() {
MaterialToolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (toolbar != null) {
toolbar.setNavigationOnClickListener(v -> finish());
}
imageProfile = findViewById(R.id.imageProfile);
editName = findViewById(R.id.editName);
// In XML it is present as @+id/textEmail inside cardSecurity.
textEmail = findViewById(R.id.textEmail);
btnSaveAll = findViewById(R.id.btnSaveAll);
btnChangeEmail = findViewById(R.id.btnChangeEmail);
btnChangePassword = findViewById(R.id.btnChangePassword);
btnLogout = findViewById(R.id.btnLogout);
// New FAB for editing photo
btnChangePhoto = findViewById(R.id.fabEditPhoto);
// Also allow clicking the text
View btnChangePhotoText = findViewById(R.id.btnChangePhoto);
cardImageContainer = findViewById(R.id.cardImageContainer);
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("A processar...");
progressDialog.setCancelable(false);
// Setup listeners here or in setupListeners()
if (btnChangePhotoText != null) {
btnChangePhotoText.setOnClickListener(v -> openImagePicker());
}
}
private void initFirebase() {
mAuth = FirebaseAuth.getInstance();
mStorage = FirebaseStorage.getInstance();
storageRef = mStorage.getReference();
}
private void setupImagePicker() {
imagePickerLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
selectedImageUri = result.getData().getData();
if (selectedImageUri != null) {
try {
InputStream inputStream = getContentResolver().openInputStream(selectedImageUri);
if (inputStream != null) {
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
if (bitmap != null) {
imageProfile.setImageBitmap(bitmap);
// Não fazemos upload até clicar em Gravar
} else {
Toast.makeText(this, "Erro ao carregar imagem", Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
Toast.makeText(this, "Erro ao carregar imagem: " + e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
}
});
}
private void setupPermissionLauncher() {
permissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
isGranted -> {
if (isGranted) {
openImagePicker();
} else {
Toast.makeText(this, "Permissão necessária para selecionar imagem", Toast.LENGTH_SHORT).show();
}
});
}
private void loadUserData() {
FirebaseUser user = mAuth.getCurrentUser();
if (user != null) {
// Carregar email
if (textEmail != null) {
textEmail.setText(user.getEmail() != null ? user.getEmail() : "");
}
// Carregar nome
if (editName != null && user.getDisplayName() != null && !user.getDisplayName().isEmpty()) {
editName.setText(user.getDisplayName());
}
// Carregar foto de perfil
if (user.getPhotoUrl() != null) {
loadProfileImage(user.getPhotoUrl().toString());
} else {
// Tentar carregar do Storage
loadProfileImageFromStorage();
}
} else {
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
finish();
}
}
private void loadProfileImage(String imageUrl) {
new Thread(() -> {
InputStream input = null;
try {
java.net.URL url = new java.net.URL(imageUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
runOnUiThread(() -> {
if (bitmap != null && imageProfile != null) {
imageProfile.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
runOnUiThread(() -> loadProfileImageFromStorage());
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
// Ignorar erro ao fechar
}
}
}
}).start();
}
private void loadProfileImageFromStorage() {
FirebaseUser user = mAuth.getCurrentUser();
if (user == null)
return;
StorageReference profileImageRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> {
loadProfileImage(uri.toString());
}).addOnFailureListener(e -> {
// Foto não encontrada, manter imagem padrão
});
}
private void setupListeners() {
if (btnChangePhoto != null) {
btnChangePhoto.setOnClickListener(v -> openImagePicker());
}
if (cardImageContainer != null) {
cardImageContainer.setOnClickListener(v -> openImagePicker());
}
if (btnSaveAll != null) {
btnSaveAll.setOnClickListener(v -> saveAllChanges());
}
if (btnChangeEmail != null) {
btnChangeEmail.setOnClickListener(v -> sendEmailVerificationForEmailChange());
}
if (btnChangePassword != null) {
btnChangePassword.setOnClickListener(v -> sendPasswordResetEmail());
}
if (btnLogout != null) {
btnLogout.setOnClickListener(v -> showLogoutConfirmation());
}
}
private void openImagePicker() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imagePickerLauncher.launch(intent);
} else {
String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
imagePickerLauncher.launch(intent);
} else {
permissionLauncher.launch(permission);
}
}
}
private void saveAllChanges() {
if (editName == null)
return;
String newName = editName.getText().toString().trim();
if (newName.isEmpty() && selectedImageUri == null) {
Toast.makeText(this, "Nenhuma alteração a guardar", Toast.LENGTH_SHORT).show();
return;
}
FirebaseUser user = mAuth.getCurrentUser();
if (user == null) {
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
return;
}
progressDialog.show();
// Se tiver foto nova, primeiro faz upload
if (selectedImageUri != null) {
uploadNewProfileImageAndSaveName(user, newName);
} else {
// Só muda o nome
saveNameOnly(user, newName);
}
}
private void saveNameOnly(FirebaseUser user, String newName) {
if (newName.isEmpty()) {
progressDialog.dismiss();
return; // Se não houver nome para trocar nem imagem, já barrámos em saveAllChanges.
}
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(newName)
.build();
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this, "Alterações guardadas com sucesso!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Erro ao guardar alterações: " +
(task.getException() != null ? task.getException().getMessage() : "Erro desconhecido"),
Toast.LENGTH_SHORT).show();
}
});
}
private void uploadNewProfileImageAndSaveName(FirebaseUser user, String newName) {
InputStream inputStream = null;
try {
inputStream = getContentResolver().openInputStream(selectedImageUri);
if (inputStream == null) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao abrir imagem", Toast.LENGTH_SHORT).show();
return;
}
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap == null) {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao processar imagem", Toast.LENGTH_SHORT).show();
return;
}
// Redimensionar
int maxSize = 1024;
if (bitmap.getWidth() > maxSize || bitmap.getHeight() > maxSize) {
float scale = Math.min((float) maxSize / bitmap.getWidth(), (float) maxSize / bitmap.getHeight());
int newWidth = Math.round(bitmap.getWidth() * scale);
int newHeight = Math.round(bitmap.getHeight() * scale);
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] imageData = baos.toByteArray();
StorageReference profileImageRef = storageRef.child("profile_images/" + user.getUid() + ".jpg");
UploadTask uploadTask = profileImageRef.putBytes(imageData);
uploadTask.addOnSuccessListener(taskSnapshot -> {
profileImageRef.getDownloadUrl().addOnSuccessListener(uri -> {
UserProfileChangeRequest.Builder builder = new UserProfileChangeRequest.Builder();
builder.setPhotoUri(uri);
if (!newName.isEmpty()) {
builder.setDisplayName(newName);
}
UserProfileChangeRequest profileUpdates = builder.build();
user.updateProfile(profileUpdates).addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this, "As definições foram guardadas!", Toast.LENGTH_SHORT).show();
loadProfileImage(uri.toString());
selectedImageUri = null; // reset
} else {
Toast.makeText(this, "Erro ao atualizar perfil", Toast.LENGTH_SHORT).show();
}
});
}).addOnFailureListener(e -> {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao obter URL: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
}).addOnFailureListener(e -> {
progressDialog.dismiss();
Toast.makeText(this, "Erro ao fazer upload: " + e.getMessage(), Toast.LENGTH_SHORT).show();
});
} catch (Exception e) {
progressDialog.dismiss();
Toast.makeText(this, "Erro: " + e.getMessage(), Toast.LENGTH_SHORT).show();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
}
}
}
}
private void sendPasswordResetEmail() {
FirebaseUser user = mAuth.getCurrentUser();
if (user == null || user.getEmail() == null) {
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
return;
}
progressDialog.show();
mAuth.sendPasswordResetEmail(user.getEmail())
.addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this,
"Email de alteração de password enviado! Verifique a sua caixa de entrada.",
Toast.LENGTH_LONG).show();
} else {
String errorMessage = "Erro ao enviar email!";
if (task.getException() != null && task.getException().getMessage() != null) {
errorMessage = "Erro: " + task.getException().getMessage();
}
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
}
});
}
private void sendEmailVerificationForEmailChange() {
FirebaseUser user = mAuth.getCurrentUser();
if (user == null || user.getEmail() == null) {
Toast.makeText(this, "Utilizador não autenticado", Toast.LENGTH_SHORT).show();
return;
}
progressDialog.show();
// Enviar email de verificação para alterar email
user.sendEmailVerification()
.addOnCompleteListener(task -> {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(this,
"Email de verificação enviado! Verifique a sua caixa de entrada para alterar o email.",
Toast.LENGTH_LONG).show();
} else {
// Se não conseguir enviar email de verificação, enviar email de reset de
// password
// que pode ser usado para alterar o email através do Firebase Console
mAuth.sendPasswordResetEmail(user.getEmail())
.addOnCompleteListener(resetTask -> {
if (resetTask.isSuccessful()) {
Toast.makeText(this,
"Email enviado! Verifique a sua caixa de entrada para instruções de alteração.",
Toast.LENGTH_LONG).show();
} else {
String errorMessage = "Erro ao enviar email!";
if (resetTask.getException() != null
&& resetTask.getException().getMessage() != null) {
errorMessage = "Erro: " + resetTask.getException().getMessage();
}
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
}
});
}
});
}
private void showLogoutConfirmation() {
new AlertDialog.Builder(this)
.setTitle("Terminar Sessão")
.setMessage("Tem a certeza que deseja terminar a sessão?")
.setPositiveButton("Sim", (dialog, which) -> logoutUser())
.setNegativeButton("Cancelar", null)
.show();
}
private void logoutUser() {
// Limpar credenciais guardadas
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.apply();
// Fazer logout do Firebase
mAuth.signOut();
Toast.makeText(this, "Sessão terminada", Toast.LENGTH_SHORT).show();
// Voltar para o login
Intent intent = new Intent(ContaActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
} }
} }

View File

@@ -30,7 +30,8 @@ public class DefinicoesFragment extends Fragment {
setupUi(); setupUi();
return binding.getRoot(); return binding.getRoot();
} }
//teste
// teste
private void setupUi() { private void setupUi() {
binding.cardConta.setOnClickListener(new View.OnClickListener() { binding.cardConta.setOnClickListener(new View.OnClickListener() {
@Override @Override
@@ -44,14 +45,35 @@ public class DefinicoesFragment extends Fragment {
} }
}); });
binding.switchNotifications
binding.switchNotifications.setOnCheckedChangeListener((buttonView, isChecked) -> .setOnCheckedChangeListener((buttonView, isChecked) -> binding.textNotificationsStatus.setText(
binding.textNotificationsStatus.setText(
isChecked ? "Ativadas" : "Desativadas")); isChecked ? "Ativadas" : "Desativadas"));
binding.switchDarkMode.setOnCheckedChangeListener((buttonView, isChecked) -> // Obter SharedPreferences
binding.textDarkModeStatus.setText( android.content.SharedPreferences prefs = requireActivity().getSharedPreferences("SettingsPrefs",
isChecked ? "Ativo" : "Inativo")); android.content.Context.MODE_PRIVATE);
boolean isDarkMode = prefs.getBoolean("dark_mode", false);
binding.switchDarkMode.setChecked(isDarkMode);
binding.textDarkModeStatus.setText(isDarkMode ? "Ativo" : "Inativo");
binding.switchDarkMode.setOnCheckedChangeListener((buttonView, isChecked) -> {
binding.textDarkModeStatus.setText(isChecked ? "Ativo" : "Inativo");
// Guardar preferência
android.content.SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("dark_mode", isChecked);
editor.apply();
// Aplicar modo escuro
if (isChecked) {
androidx.appcompat.app.AppCompatDelegate
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES);
} else {
androidx.appcompat.app.AppCompatDelegate
.setDefaultNightMode(androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO);
}
});
binding.btnOpenSystemSettings.setOnClickListener(v -> { binding.btnOpenSystemSettings.setOnClickListener(v -> {
Intent intent = new Intent(Settings.ACTION_SETTINGS); Intent intent = new Intent(Settings.ACTION_SETTINGS);
@@ -66,4 +88,3 @@ public class DefinicoesFragment extends Fragment {
binding = null; binding = null;
} }
} }

View File

@@ -4,31 +4,82 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager;
import com.example.vdcscore.databinding.FragmentGalleryBinding; import com.example.vdcscore.databinding.FragmentGalleryBinding;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class GalleryFragment extends Fragment { public class GalleryFragment extends Fragment {
private FragmentGalleryBinding binding; private FragmentGalleryBinding binding;
private MatchdaysAdapter adapter;
private DatabaseReference mDatabase;
public View onCreateView(@NonNull LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) { ViewGroup container, Bundle savedInstanceState) {
GalleryViewModel galleryViewModel =
new ViewModelProvider(this).get(GalleryViewModel.class);
binding = FragmentGalleryBinding.inflate(inflater, container, false); binding = FragmentGalleryBinding.inflate(inflater, container, false);
View root = binding.getRoot(); View root = binding.getRoot();
final TextView textView = binding.textGallery; // Initialize RecyclerView
galleryViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); adapter = new MatchdaysAdapter();
binding.recyclerMatchdays.setLayoutManager(new LinearLayoutManager(getContext()));
binding.recyclerMatchdays.setAdapter(adapter);
// Initialize Firebase
mDatabase = FirebaseDatabase.getInstance().getReference("matchdays");
// Fetch Data
fetchMatchdays();
return root; return root;
} }
private void fetchMatchdays() {
mDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
List<Matchday> matchdays = new ArrayList<>();
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
Matchday matchday = new Matchday();
matchday.setId(postSnapshot.getKey());
matchday.setName(postSnapshot.child("name").getValue(String.class));
List<Match> matches = new ArrayList<>();
for (DataSnapshot matchSnapshot : postSnapshot.child("matches").getChildren()) {
Match match = matchSnapshot.getValue(Match.class);
if (match != null) {
match.setId(matchSnapshot.getKey());
matches.add(match);
}
}
matchday.setMatches(matches);
matchdays.add(matchday);
}
adapter.setMatchdays(matchdays);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
if (getContext() != null) {
Toast.makeText(getContext(), "Erro ao carregar jornadas: " + error.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
});
}
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();

View File

@@ -0,0 +1,88 @@
package com.example.vdcscore.ui.gallery;
public class Match {
private String id;
private String homeTeam;
private String awayTeam;
private int homeScore;
private int awayScore;
private String date;
private String time;
private String status; // "Scheduled", "Finished", "Live"
public Match() {
}
public Match(String homeTeam, String awayTeam, String date, String time) {
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
this.date = date;
this.time = time;
this.status = "Scheduled";
}
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHomeTeam() {
return homeTeam;
}
public void setHomeTeam(String homeTeam) {
this.homeTeam = homeTeam;
}
public String getAwayTeam() {
return awayTeam;
}
public void setAwayTeam(String awayTeam) {
this.awayTeam = awayTeam;
}
public int getHomeScore() {
return homeScore;
}
public void setHomeScore(int homeScore) {
this.homeScore = homeScore;
}
public int getAwayScore() {
return awayScore;
}
public void setAwayScore(int awayScore) {
this.awayScore = awayScore;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

View File

@@ -0,0 +1,41 @@
package com.example.vdcscore.ui.gallery;
import java.util.List;
public class Matchday {
private String id;
private String name; // e.g., "Jornada 1"
private List<Match> matches;
public Matchday() {
}
public Matchday(String name, List<Match> matches) {
this.name = name;
this.matches = matches;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Match> getMatches() {
return matches;
}
public void setMatches(List<Match> matches) {
this.matches = matches;
}
}

View File

@@ -0,0 +1,68 @@
package com.example.vdcscore.ui.gallery;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.vdcscore.R;
import java.util.ArrayList;
import java.util.List;
public class MatchdaysAdapter extends RecyclerView.Adapter<MatchdaysAdapter.ViewHolder> {
private List<Matchday> matchdays = new ArrayList<>();
private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
public void setMatchdays(List<Matchday> matchdays) {
this.matchdays = matchdays;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_matchday, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Matchday matchday = matchdays.get(position);
holder.textName.setText(matchday.getName());
// Setup nested RecyclerView
LinearLayoutManager layoutManager = new LinearLayoutManager(
holder.recyclerMatches.getContext(),
LinearLayoutManager.VERTICAL,
false);
layoutManager.setInitialPrefetchItemCount(matchday.getMatches().size());
MatchesAdapter matchesAdapter = new MatchesAdapter(matchday.getMatches());
holder.recyclerMatches.setLayoutManager(layoutManager);
holder.recyclerMatches.setAdapter(matchesAdapter);
holder.recyclerMatches.setRecycledViewPool(viewPool);
}
@Override
public int getItemCount() {
return matchdays.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView textName;
public final RecyclerView recyclerMatches;
public ViewHolder(View view) {
super(view);
textName = view.findViewById(R.id.text_matchday_name);
recyclerMatches = view.findViewById(R.id.recycler_matches);
}
}
}

View File

@@ -0,0 +1,65 @@
package com.example.vdcscore.ui.gallery;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.vdcscore.R;
import java.util.List;
public class MatchesAdapter extends RecyclerView.Adapter<MatchesAdapter.ViewHolder> {
private List<Match> matches;
public MatchesAdapter(List<Match> matches) {
this.matches = matches;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_match, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Match match = matches.get(position);
holder.textHomeTeam.setText(match.getHomeTeam());
holder.textAwayTeam.setText(match.getAwayTeam());
if ("Finished".equals(match.getStatus())) {
holder.textScore.setText(match.getHomeScore() + " - " + match.getAwayScore());
holder.textTime.setText("Final");
} else {
holder.textScore.setText("Vs");
holder.textTime.setText(match.getTime());
}
}
@Override
public int getItemCount() {
return matches == null ? 0 : matches.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView textHomeTeam;
public final TextView textAwayTeam;
public final TextView textScore;
public final TextView textTime;
public ViewHolder(View view) {
super(view);
textHomeTeam = view.findViewById(R.id.text_home_team);
textAwayTeam = view.findViewById(R.id.text_away_team);
textScore = view.findViewById(R.id.text_score);
textTime = view.findViewById(R.id.text_time);
}
}
}

View File

@@ -4,31 +4,90 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager;
import com.example.vdcscore.databinding.FragmentHomeBinding; import com.example.vdcscore.databinding.FragmentHomeBinding;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class HomeFragment extends Fragment { public class HomeFragment extends Fragment {
private FragmentHomeBinding binding; private FragmentHomeBinding binding;
private StandingsAdapter adapter;
private DatabaseReference mDatabase;
public View onCreateView(@NonNull LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) { ViewGroup container, Bundle savedInstanceState) {
HomeViewModel homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
binding = FragmentHomeBinding.inflate(inflater, container, false); binding = FragmentHomeBinding.inflate(inflater, container, false);
View root = binding.getRoot(); View root = binding.getRoot();
final TextView textView = binding.textHome; // Initialize RecyclerView
homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); adapter = new StandingsAdapter();
binding.recyclerStandings.setLayoutManager(new LinearLayoutManager(getContext()));
binding.recyclerStandings.setAdapter(adapter);
// Initialize Firebase
mDatabase = FirebaseDatabase.getInstance().getReference("standings");
// Fetch Data
fetchStandings();
return root; return root;
} }
private void fetchStandings() {
mDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
List<Team> teams = new ArrayList<>();
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
Team team = postSnapshot.getValue(Team.class);
if (team != null) {
// If ID is missing, set it from the key
if (team.getId() == null) {
team.setId(postSnapshot.getKey());
}
teams.add(team);
}
}
// Sort by Points (Descending), then Goal Difference, then Goals For
Collections.sort(teams, new Comparator<Team>() {
@Override
public int compare(Team t1, Team t2) {
if (t1.getPoints() != t2.getPoints()) {
return t2.getPoints() - t1.getPoints(); // Descending points
}
return t2.getGoalDifference() - t1.getGoalDifference(); // Descending GD
}
});
adapter.setTeams(teams);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
if (getContext() != null) {
Toast.makeText(getContext(), "Erro ao carregar classificação: " + error.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
});
}
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();

View File

@@ -0,0 +1,66 @@
package com.example.vdcscore.ui.home;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.vdcscore.R;
import java.util.ArrayList;
import java.util.List;
public class StandingsAdapter extends RecyclerView.Adapter<StandingsAdapter.ViewHolder> {
private List<Team> mTeams;
public StandingsAdapter() {
this.mTeams = new ArrayList<>();
}
public void setTeams(List<Team> teams) {
this.mTeams = teams;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_standing, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Team team = mTeams.get(position);
holder.textPosition.setText(String.valueOf(position + 1));
holder.textTeamName.setText(team.getName());
holder.textPlayed.setText(String.valueOf(team.getPlayed()));
holder.textPoints.setText(String.valueOf(team.getPoints()));
}
@Override
public int getItemCount() {
return mTeams.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView textPosition;
public final TextView textTeamName;
public final TextView textPlayed;
public final TextView textPoints;
public ViewHolder(View view) {
super(view);
textPosition = view.findViewById(R.id.text_position);
textTeamName = view.findViewById(R.id.text_team_name);
textPlayed = view.findViewById(R.id.text_played);
textPoints = view.findViewById(R.id.text_points);
}
}
}

View File

@@ -0,0 +1,106 @@
package com.example.vdcscore.ui.home;
public class Team {
private String id;
private String name;
private int points;
private int played;
private int won;
private int drawn;
private int lost;
private int goalsFor;
private int goalsAgainst;
private int goalDifference;
public Team() {
// Required empty constructor for Firebase
}
public Team(String id, String name, int points, int played) {
this.id = id;
this.name = name;
this.points = points;
this.played = played;
}
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public int getPlayed() {
return played;
}
public void setPlayed(int played) {
this.played = played;
}
public int getWon() {
return won;
}
public void setWon(int won) {
this.won = won;
}
public int getDrawn() {
return drawn;
}
public void setDrawn(int drawn) {
this.drawn = drawn;
}
public int getLost() {
return lost;
}
public void setLost(int lost) {
this.lost = lost;
}
public int getGoalsFor() {
return goalsFor;
}
public void setGoalsFor(int goalsFor) {
this.goalsFor = goalsFor;
}
public int getGoalsAgainst() {
return goalsAgainst;
}
public void setGoalsAgainst(int goalsAgainst) {
this.goalsAgainst = goalsAgainst;
}
public int getGoalDifference() {
return goalDifference;
}
public void setGoalDifference(int goalDifference) {
this.goalDifference = goalDifference;
}
}

View File

@@ -0,0 +1,68 @@
package com.example.vdcscore.ui.livegames;
public class Game {
private String id;
private String homeTeam;
private String awayTeam;
private int homeScore;
private int awayScore;
private String time;
private int homePossession;
private int awayPossession;
private int homeShots;
private int awayShots;
public Game(String id, String homeTeam, String awayTeam, int homeScore, int awayScore, String time) {
this.id = id;
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
this.homeScore = homeScore;
this.awayScore = awayScore;
this.time = time;
// Default mocked stats
this.homePossession = 50;
this.awayPossession = 50;
this.homeShots = 5;
this.awayShots = 3;
}
public String getId() {
return id;
}
public String getHomeTeam() {
return homeTeam;
}
public String getAwayTeam() {
return awayTeam;
}
public int getHomeScore() {
return homeScore;
}
public int getAwayScore() {
return awayScore;
}
public String getTime() {
return time;
}
public int getHomePossession() {
return homePossession;
}
public int getAwayPossession() {
return awayPossession;
}
public int getHomeShots() {
return homeShots;
}
public int getAwayShots() {
return awayShots;
}
}

View File

@@ -0,0 +1,71 @@
package com.example.vdcscore.ui.livegames;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.vdcscore.R;
import java.util.List;
public class GameAdapter extends RecyclerView.Adapter<GameAdapter.GameViewHolder> {
private final List<Game> mGames;
private final OnGameClickListener mListener;
public interface OnGameClickListener {
void onGameClick(Game game);
}
public GameAdapter(List<Game> games, OnGameClickListener listener) {
mGames = games;
mListener = listener;
}
@NonNull
@Override
public GameViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_live_game, parent, false);
return new GameViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull GameViewHolder holder, int position) {
Game game = mGames.get(position);
holder.bind(game, mListener);
}
@Override
public int getItemCount() {
return mGames.size();
}
static class GameViewHolder extends RecyclerView.ViewHolder {
private final TextView time;
private final TextView homeTeam;
private final TextView awayTeam;
private final TextView score;
public GameViewHolder(@NonNull View itemView) {
super(itemView);
time = itemView.findViewById(R.id.text_game_time);
homeTeam = itemView.findViewById(R.id.text_home_team);
awayTeam = itemView.findViewById(R.id.text_away_team);
score = itemView.findViewById(R.id.text_score);
}
public void bind(final Game game, final OnGameClickListener listener) {
time.setText(game.getTime());
homeTeam.setText(game.getHomeTeam());
awayTeam.setText(game.getAwayTeam());
score.setText(game.getHomeScore() + " - " + game.getAwayScore());
itemView.setOnClickListener(v -> listener.onGameClick(game));
}
}
}

View File

@@ -0,0 +1,40 @@
package com.example.vdcscore.ui.livegames;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import java.util.ArrayList;
import java.util.List;
public class GameViewModel extends ViewModel {
private final MutableLiveData<List<Game>> mGames;
private final MutableLiveData<Game> mSelectedGame;
public GameViewModel() {
mGames = new MutableLiveData<>();
mSelectedGame = new MutableLiveData<>();
loadMockGames();
}
public LiveData<List<Game>> getGames() {
return mGames;
}
public LiveData<Game> getSelectedGame() {
return mSelectedGame;
}
public void selectGame(Game game) {
mSelectedGame.setValue(game);
}
private void loadMockGames() {
List<Game> games = new ArrayList<>();
games.add(new Game("1", "VDC", "Benfica", 2, 1, "45'"));
games.add(new Game("2", "Sporting", "Porto", 0, 0, "12'"));
games.add(new Game("3", "Braga", "V. Guimarães", 1, 3, "88'"));
mGames.setValue(games);
}
}

View File

@@ -0,0 +1,53 @@
package com.example.vdcscore.ui.livegames;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.ProgressBar;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.vdcscore.R;
import com.example.vdcscore.databinding.FragmentLiveGameDetailBinding;
public class LiveGameDetailFragment extends Fragment {
private FragmentLiveGameDetailBinding binding;
private GameViewModel gameViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
gameViewModel = new ViewModelProvider(requireActivity()).get(GameViewModel.class);
binding = FragmentLiveGameDetailBinding.inflate(inflater, container, false);
View root = binding.getRoot();
gameViewModel.getSelectedGame().observe(getViewLifecycleOwner(), game -> {
if (game != null) {
binding.detailGameTime.setText(game.getTime());
binding.detailHomeTeam.setText(game.getHomeTeam());
binding.detailAwayTeam.setText(game.getAwayTeam());
binding.detailScore.setText(game.getHomeScore() + " - " + game.getAwayScore());
binding.progressPossession.setProgress(game.getHomePossession());
binding.textPossessionHome.setText(game.getHomePossession() + "%");
binding.textPossessionAway.setText(game.getAwayPossession() + "%");
binding.textShotsHome.setText(String.valueOf(game.getHomeShots()));
binding.textShotsAway.setText(String.valueOf(game.getAwayShots()));
}
});
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@@ -0,0 +1,49 @@
package com.example.vdcscore.ui.livegames;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.vdcscore.R;
import com.example.vdcscore.databinding.FragmentLiveGamesBinding;
public class LiveGamesFragment extends Fragment {
private FragmentLiveGamesBinding binding;
private GameViewModel gameViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
gameViewModel = new ViewModelProvider(requireActivity()).get(GameViewModel.class);
binding = FragmentLiveGamesBinding.inflate(inflater, container, false);
View root = binding.getRoot();
RecyclerView recyclerView = binding.recyclerLiveGames;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
gameViewModel.getGames().observe(getViewLifecycleOwner(), games -> {
GameAdapter adapter = new GameAdapter(games, game -> {
gameViewModel.selectGame(game);
Navigation.findNavController(root).navigate(R.id.action_nav_live_games_to_nav_live_game_detail);
});
recyclerView.setAdapter(adapter);
});
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<corners
android:topLeftRadius="30dp"
android:topRightRadius="30dp" />
</shape>

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="6dp" />
<solid android:color="#E0E0E0" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="6dp" />
<solid android:color="@color/secondary_color" />
</shape>
</clip>
</item>
</layer-list>

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="@color/primary_color"/>
<corners android:radius="8dp"/>
</shape>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,4h-1V2h-2v2H8V2H6v2H5c-1.11,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2zM19,20H5V10h14v10zM19,8H5V6h14v2z"/>
</vector>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="412dp"
android:height="300dp"
android:viewportWidth="412"
android:viewportHeight="300">
<path
android:fillColor="#121212"
android:pathData="M0,0 L412,0 L412,220 C412,220 300,300 0,220 L0,0 Z" />
</vector>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="412dp"
android:height="200dp"
android:viewportWidth="412"
android:viewportHeight="200">
<path
android:fillColor="#121212"
android:pathData="M0,0 L412,0 L412,150 C300,200 100,200 0,150 L0,0 Z" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

View File

@@ -1,30 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-0.96 -0.78,-1.85 -1.35,-2.68 1.69,0.25 3.19,1.21 4.3,2.68zM14.53,7.69c-0.23,-0.69 -0.52,-1.36 -0.86,-1.99 -0.87,-0.3 -1.8,-0.48 -2.77,-0.48 -0.41,0 -0.81,0.04 -1.2,0.1 0.72,0.92 1.25,2.02 1.51,3.22h3.32zM8.33,5.32c-0.58,0.83 -1.04,1.72 -1.35,2.68H4.08c1.11,-1.47 2.61,-2.43 4.25,-2.68zM4.26,16h3.1c0.41,1.12 1.05,2.15 1.87,3.01 -1.97,-0.47 -3.67,-1.55 -4.97,-3.01zM4,12c0,-1.39 0.42,-2.68 1.13,-3.76 0.18,0.07 0.36,0.13 0.53,0.21 0.42,1.38 1.1,2.63 2,3.7 -0.85,1.02 -1.5,2.2 -1.92,3.5 0,0 -0.01,0 -0.01,0 -1.05,-1.03 -1.73,-2.45 -1.73,-4.06zM11.9,16.5c-1.3,0 -2.48,-0.62 -3.26,-1.59 0.73,-0.89 1.27,-1.93 1.57,-3.06h3.76l0,0c0.3,1.13 0.85,2.17 1.56,3.06 -0.78,0.97 -1.96,1.59 -3.26,1.59zM14.77,19.01c0.82,-0.86 1.46,-1.89 1.88,-3.01h3.1c-1.3,1.46 -3.01,2.54 -4.98,3.01zM17.16,11.94c0.42,-1.29 1.07,-2.48 1.92,-3.5 1.04,1.06 1.72,2.49 1.72,4.06 0,0.15 -0.01,0.29 -0.02,0.44 -1.13,-1.47 -2.62,-2.55 -4.26,-2.81 -0.19,0.64 -0.46,1.25 -0.78,1.82 0.5,0.38 0.98,0.81 1.42,1.29v-1.3z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/live_indicator" />
</shape>

View File

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

View File

@@ -1,10 +1,301 @@
<?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" <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/background_light"
tools:context=".ui.definicoes.ContaActivity"> tools:context=".ui.definicoes.ContaActivity">
</androidx.constraintlayout.widget.ConstraintLayout> <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:elevation="0dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary_color"
app:title="Definições de Conta"
app:titleTextColor="@color/white"
app:navigationIcon="@drawable/ic_arrow_back"
app:navigationIconTint="@color/white" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<!-- Profile Photo Section -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardProfilePhoto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@color/surface_card"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Foto de Perfil"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_marginBottom="24dp" />
<!-- Profile Image -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardImageContainer"
android:layout_width="120dp"
android:layout_height="120dp"
app:cardCornerRadius="60dp"
app:cardElevation="6dp"
app:cardBackgroundColor="#FFFFFF"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackgroundBorderless">
<ImageView
android:id="@+id/imageProfile"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:contentDescription="Foto de perfil"
android:src="@android:drawable/ic_menu_camera"
android:background="#E0E0E0" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabEditPhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fabSize="mini"
app:backgroundTint="@color/secondary_color"
app:tint="@color/white"
android:src="@android:drawable/ic_menu_edit"
app:layout_constraintBottom_toBottomOf="@+id/cardImageContainer"
app:layout_constraintEnd_toEndOf="@+id/cardImageContainer"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/btnChangePhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Toque para alterar"
android:textColor="@color/text_secondary"
android:textSize="14sp"
android:textStyle="bold"
android:clickable="true"
android:focusable="true"
android:padding="8dp"
android:background="?attr/selectableItemBackgroundBorderless" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Name Section -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@color/surface_card"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome de Utilizador"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_marginBottom="16dp" />
<!-- Name Input -->
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Nome completo"
app:boxCornerRadiusTopStart="12dp"
app:boxCornerRadiusTopEnd="12dp"
app:boxCornerRadiusBottomStart="12dp"
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="1dp"
app:boxStrokeColor="@color/divider"
app:startIconDrawable="@android:drawable/ic_menu_myplaces"
app:startIconTint="@color/text_secondary"
app:boxBackgroundMode="outline"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/editName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:textColor="@color/text_primary"
android:textColorHint="@color/text_secondary"
android:textSize="16sp"
android:padding="16dp"
android:background="@android:color/transparent" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btnSaveAll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:backgroundTint="@color/primary_color"
android:text="Guardar Alterações"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Security Section -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardSecurity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@color/surface_card"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Segurança"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/primary_color"
android:layout_marginBottom="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="@color/text_secondary"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/textEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="email@exemplo.com"
android:textSize="16sp"
android:textColor="@color/text_primary"
android:padding="12dp"
android:background="@drawable/shape_score_bg"
android:backgroundTint="@color/background_light"
android:layout_marginBottom="12dp" />
<Button
android:id="@+id/btnChangeEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/text_secondary"
android:text="Alterar Email"
android:textColor="@color/white" />
<Button
android:id="@+id/btnChangePassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:backgroundTint="@color/text_secondary"
android:text="Alterar Password"
android:textColor="@color/white" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Logout Section -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardLogout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@color/surface_card"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<Button
android:id="@+id/btnLogout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/live_time"
android:text="Terminar Sessão"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -3,213 +3,189 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/bg_gradient" android:background="#FFFFFF">
android:id="@+id/main">
<!-- Logo/Title --> <!-- Header Background -->
<ImageView
android:id="@+id/headerBg"
android:layout_width="match_parent"
android:layout_height="250dp"
android:scaleType="fitXY"
android:src="@drawable/ic_header_signup_bg"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<!-- Header Title (as per design image, showing "Sign Up" in header) or Body?
The image shows "Sign Up" text in the header area. -->
<TextView <TextView
android:id="@+id/textView4"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="60dp" android:text="Sign Up"
android:text="VdcScore" android:textColor="#FFFFFF"
android:textSize="42sp" android:textSize="32sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:layout_marginTop="60dp"
android:letterSpacing="0.1" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
<!-- Subtitle --> <!-- Back Button (Optional, not in Java but good for UX) -->
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Criar Conta"
android:textSize="16sp"
android:textColor="#FFFFFF"
android:alpha="0.9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView4" />
<!-- Card -->
<androidx.cardview.widget.CardView <!-- Sign Up Form Container -->
android:id="@+id/cardRegister" <ScrollView
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_marginStart="24dp" android:fillViewport="true"
android:layout_marginEnd="24dp" android:layout_marginTop="160dp"
android:layout_marginTop="40dp" app:layout_constraintTop_toTopOf="parent"
android:elevation="8dp" app:layout_constraintBottom_toBottomOf="parent">
android:padding="28dp"
app:cardCornerRadius="24dp"
app:cardBackgroundColor="#FFFFFF"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical"
android:paddingHorizontal="32dp"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:background="@drawable/bg_bottom_sheet_curve"> <!-- Implicit white background from activity, but layout structure follows scrolling -->
<!-- Title inside card --> <!-- User Name Label -->
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Registo" android:text="Nome de Utilizador"
android:textSize="28sp" android:textColor="#212121"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#263238" android:layout_marginBottom="8dp"
android:layout_marginBottom="8dp" /> android:layout_marginStart="4dp"/>
<TextView <com.google.android.material.textfield.TextInputEditText
android:layout_width="wrap_content" android:id="@+id/editUserName"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:text="Cria a tua conta" android:layout_height="50dp"
android:background="@drawable/bg_input_field"
android:paddingHorizontal="16dp"
android:inputType="textPersonName"
android:hint="Tony"
android:textColor="#424242"
android:textColorHint="#BDBDBD"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#90A4AE"
android:layout_marginBottom="24dp" /> android:layout_marginBottom="24dp" />
<!-- Email --> <!-- Email Label -->
<com.google.android.material.textfield.TextInputLayout <TextView
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dp" android:text="Email"
android:hint="Email" android:textColor="#212121"
app:boxCornerRadiusTopStart="12dp" android:textStyle="bold"
app:boxCornerRadiusTopEnd="12dp" android:layout_marginBottom="8dp"
app:boxCornerRadiusBottomStart="12dp" android:layout_marginStart="4dp"/>
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:startIconDrawable="@android:drawable/ic_dialog_email"
app:startIconTint="#667eea"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/editEmail" android:id="@+id/editEmail"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="50dp"
android:background="@drawable/bg_input_field"
android:paddingHorizontal="16dp"
android:inputType="textEmailAddress" android:inputType="textEmailAddress"
android:textColor="#263238" android:hint="email@exemplo.com"
android:textColorHint="#90A4AE" android:textColor="#424242"
android:padding="16dp" /> android:textColorHint="#BDBDBD"
android:textSize="14sp"
android:layout_marginBottom="24dp" />
</com.google.android.material.textfield.TextInputLayout> <!-- Password Label -->
<TextView
<!-- Password --> android:layout_width="wrap_content"
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dp" android:text="Password"
android:hint="Password" android:textColor="#212121"
app:boxCornerRadiusTopStart="12dp" android:textStyle="bold"
app:boxCornerRadiusTopEnd="12dp" android:layout_marginBottom="8dp"
app:boxCornerRadiusBottomStart="12dp" android:layout_marginStart="4dp"/>
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:startIconDrawable="@android:drawable/ic_lock_lock"
app:startIconTint="#667eea"
app:endIconMode="password_toggle"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/editPassword2" android:id="@+id/editPassword2"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="50dp"
android:background="@drawable/bg_input_field"
android:paddingHorizontal="16dp"
android:inputType="textPassword" android:inputType="textPassword"
android:textColor="#263238" android:hint="********"
android:textColorHint="#90A4AE" android:textColor="#424242"
android:padding="16dp" /> android:textColorHint="#BDBDBD"
android:textSize="14sp"
android:layout_marginBottom="24dp" />
</com.google.android.material.textfield.TextInputLayout> <!-- Confirm Password Label -->
<TextView
<!-- Confirmar Password --> android:layout_width="wrap_content"
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="24dp" android:text="Confirmar Password"
android:hint="Confirmar Password" android:textColor="#212121"
app:boxCornerRadiusTopStart="12dp" android:textStyle="bold"
app:boxCornerRadiusTopEnd="12dp" android:layout_marginBottom="8dp"
app:boxCornerRadiusBottomStart="12dp" android:layout_marginStart="4dp"/>
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:startIconDrawable="@android:drawable/ic_lock_lock"
app:startIconTint="#667eea"
app:endIconMode="password_toggle"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/editConfirmPassword" android:id="@+id/editConfirmPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="50dp"
android:background="@drawable/bg_input_field"
android:paddingHorizontal="16dp"
android:inputType="textPassword" android:inputType="textPassword"
android:textColor="#263238" android:hint="********"
android:textColorHint="#90A4AE" android:textColor="#424242"
android:padding="16dp" /> android:textColorHint="#BDBDBD"
android:textSize="14sp"
android:layout_marginBottom="32dp" />
</com.google.android.material.textfield.TextInputLayout>
<!-- Botão --> <!-- Sign Up Button -->
<Button <Button
android:id="@+id/btnCreateAccount" android:id="@+id/btnCreateAccount"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="56dp" android:layout_height="55dp"
android:layout_marginTop="8dp" android:text="Sign Up"
android:background="@drawable/button_modern" android:textAllCaps="false"
android:text="Criar Conta"
android:textColor="#FFFFFF"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:elevation="4dp" android:textColor="#FFFFFF"
android:stateListAnimator="@null" /> android:backgroundTint="#000000"
app:cornerRadius="12dp"
android:layout_marginBottom="24dp" />
</LinearLayout> <!-- Login Link -->
</androidx.cardview.widget.CardView>
<!-- Voltar ao Login -->
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="center" android:gravity="center">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardRegister">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Já tens conta? " android:text="Já tem uma conta? "
android:textColor="#FFFFFF" android:textColor="#757575" />
android:textSize="14sp"
android:alpha="0.9" />
<TextView <TextView
android:id="@+id/txtGoLogin" android:id="@+id/txtGoLogin"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Entrar" android:text="Sign In"
android:textColor="#FFFFFF" android:textColor="#000000"
android:textStyle="bold" android:textStyle="bold"
android:textSize="14sp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"/>
android:padding="4dp"
android:background="?attr/selectableItemBackground" />
</LinearLayout> </LinearLayout>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -5,197 +5,177 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/bg_gradient"> android:background="#FFFFFF">
<!-- Logo/Title --> <!-- Header Background -->
<TextView <ImageView
android:id="@+id/textView3" android:id="@+id/headerBg"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="300dp"
android:layout_marginTop="80dp" android:scaleType="fitXY"
android:text="VdcScore" android:src="@drawable/ic_header_login_bg"
android:textSize="42sp" app:layout_constraintTop_toTopOf="parent"
android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent"
android:textColor="#FFFFFF" app:layout_constraintStart_toStartOf="parent" />
android:letterSpacing="0.1"
<!-- Logo -->
<ImageView
android:id="@+id/logoImage"
android:layout_width="77dp"
android:layout_height="80dp"
android:layout_marginTop="60dp"
android:elevation="4dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<!-- Subtitle --> <!-- Login Form Container -->
<TextView <ScrollView
android:id="@+id/textSubtitle" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="0dp"
android:layout_height="wrap_content" android:fillViewport="true"
android:layout_marginTop="8dp" android:layout_marginTop="-40dp"
android:text="Bem-vindo de volta" app:layout_constraintTop_toBottomOf="@+id/headerBg"
android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent">
android:textColor="#FFFFFF"
android:alpha="0.9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<!-- Card -->
<androidx.cardview.widget.CardView
android:id="@+id/cardLogin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginTop="48dp"
android:elevation="8dp"
android:padding="28dp"
app:cardCornerRadius="24dp"
app:cardBackgroundColor="#FFFFFF"
app:cardUseCompatPadding="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textSubtitle">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical"
android:paddingHorizontal="32dp"
android:paddingTop="20dp"
android:paddingBottom="20dp">
<!-- Title inside card -->
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Login" android:text="Login"
android:textSize="28sp" android:textSize="32sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#263238" android:textColor="#212121"
android:layout_marginBottom="8dp" /> android:layout_gravity="center_horizontal"
android:layout_marginBottom="40dp" />
<!-- Email Label -->
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Entre na sua conta" android:text="Email"
android:textSize="14sp" android:textColor="#212121"
android:textColor="#90A4AE" android:textStyle="bold"
android:layout_marginBottom="24dp" /> android:layout_marginBottom="8dp"
android:layout_marginStart="4dp"/>
<!-- Email -->
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Email"
app:boxCornerRadiusTopStart="12dp"
app:boxCornerRadiusTopEnd="12dp"
app:boxCornerRadiusBottomStart="12dp"
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:startIconDrawable="@android:drawable/ic_dialog_email"
app:startIconTint="#667eea"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<!-- Email Input -->
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/editEmail" android:id="@+id/editEmail"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="50dp"
android:background="@drawable/bg_input_field"
android:paddingHorizontal="16dp"
android:inputType="textEmailAddress" android:inputType="textEmailAddress"
android:textColor="#263238" android:hint="email@exemplo.com"
android:textColorHint="#90A4AE" android:textColor="#424242"
android:padding="16dp" /> android:textColorHint="#BDBDBD"
android:textSize="14sp"
android:layout_marginBottom="24dp" />
</com.google.android.material.textfield.TextInputLayout> <!-- Password Label -->
<TextView
<!-- Password --> android:layout_width="wrap_content"
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Password"
android:textColor="#212121"
android:textStyle="bold"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:hint="Password" android:layout_marginStart="4dp"/>
app:boxCornerRadiusTopStart="12dp"
app:boxCornerRadiusTopEnd="12dp"
app:boxCornerRadiusBottomStart="12dp"
app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:startIconDrawable="@android:drawable/ic_lock_lock"
app:startIconTint="#667eea"
app:endIconMode="password_toggle"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<!-- Password Input -->
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/editPassword2" android:id="@+id/editPassword2"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="50dp"
android:background="@drawable/bg_input_field"
android:paddingHorizontal="16dp"
android:inputType="textPassword" android:inputType="textPassword"
android:textColor="#263238" android:hint="********"
android:textColorHint="#90A4AE" android:textColor="#424242"
android:padding="16dp" /> android:textColorHint="#BDBDBD"
android:textSize="14sp"
android:layout_marginBottom="16dp" />
</com.google.android.material.textfield.TextInputLayout> <!-- Remember Me & Forgot Password -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="32dp">
<CheckBox
android:id="@+id/checkRememberMe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Lembrar"
android:textColor="#757575"/>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<!-- Forgot Password Link -->
<TextView <TextView
android:id="@+id/txtForgotPassword" android:id="@+id/txtForgotPassword"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end" android:text="Esqueceu a senha?"
android:layout_marginBottom="24dp" android:textColor="#757575"
android:text="Esqueceu a palavra-passe?"
android:textColor="#667eea"
android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
android:textSize="12sp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"/>
android:padding="4dp" /> </LinearLayout>
<!-- Botão --> <!-- Login Button -->
<Button <Button
android:id="@+id/btnLogin" android:id="@+id/btnLogin"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="56dp" android:layout_height="55dp"
android:layout_marginTop="8dp" android:text="Login"
android:background="@drawable/button_modern" android:textAllCaps="false"
android:text="Entrar"
android:textColor="#FFFFFF"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:elevation="4dp" android:textColor="#FFFFFF"
android:stateListAnimator="@null" /> android:backgroundTint="#000000"
app:cornerRadius="12dp"
android:layout_marginBottom="24dp" />
</LinearLayout> <!-- Sign Up Link -->
</androidx.cardview.widget.CardView>
<!-- Criar conta -->
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="center" android:gravity="center">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardLogin">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Não tens conta? " android:text="Não tem uma conta? "
android:textColor="#FFFFFF" android:textColor="#757575" />
android:textSize="14sp"
android:alpha="0.9" />
<TextView <TextView
android:id="@+id/txtRegister" android:id="@+id/txtRegister"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Criar conta" android:text="Criar Conta"
android:textColor="#FFFFFF" android:textColor="#000000"
android:textStyle="bold" android:textStyle="bold"
android:textSize="14sp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"/>
android:padding="4dp"
android:background="?attr/selectableItemBackground" />
</LinearLayout> </LinearLayout>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -20,6 +20,9 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="start" android:layout_gravity="start"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
android:background="@color/white"
app:itemTextColor="@color/black"
app:itemIconTint="@color/black"
app:headerLayout="@layout/nav_header_main" app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" /> app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout> </androidx.drawerlayout.widget.DrawerLayout>

View File

@@ -85,7 +85,6 @@
app:boxCornerRadiusBottomStart="12dp" app:boxCornerRadiusBottomStart="12dp"
app:boxCornerRadiusBottomEnd="12dp" app:boxCornerRadiusBottomEnd="12dp"
app:boxStrokeWidth="0dp" app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:startIconDrawable="@android:drawable/ic_dialog_email" app:startIconDrawable="@android:drawable/ic_dialog_email"
app:startIconTint="#667eea" app:startIconTint="#667eea"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> style="@style/Widget.Material3.TextInputLayout.OutlinedBox">

View File

@@ -9,26 +9,21 @@
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:theme="@style/Theme.VdcScore.AppBarOverlay"> android:background="@color/white"
android:theme="@style/ThemeOverlay.AppCompat.Light"> <!-- Light theme for dark text -->
<androidx.appcompat.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" android:background="@color/white"
app:titleTextColor="@color/black"
app:popupTheme="@style/Theme.VdcScore.PopupOverlay" /> app:popupTheme="@style/Theme.VdcScore.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main" /> <include layout="@layout/content_main" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="@color/white"
tools:context=".ui.clubs.ClubDetailFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<!-- Club Logo (Circular) -->
<androidx.cardview.widget.CardView
android:id="@+id/cardLogo"
android:layout_width="200dp"
android:layout_height="200dp"
app:cardCornerRadius="100dp"
app:cardElevation="8dp"
app:cardBackgroundColor="@color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp">
<ImageView
android:id="@+id/image_detail_logo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:padding="0dp"
tools:src="@mipmap/ic_launcher_round"/>
</androidx.cardview.widget.CardView>
<!-- CLUBE Label -->
<TextView
android:id="@+id/label_club"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CLUBE:"
android:textSize="14sp"
android:textColor="#616161"
android:layout_marginTop="32dp"
app:layout_constraintTop_toBottomOf="@id/cardLogo"
app:layout_constraintStart_toStartOf="parent"/>
<!-- Club Name -->
<TextView
android:id="@+id/text_detail_club_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
tools:text="Inter Freguesias Vila do Conde"
android:textSize="28sp"
android:textStyle="bold"
android:textColor="#0D47A1"
android:layout_marginTop="4dp"
app:layout_constraintTop_toBottomOf="@id/label_club"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<!-- President Section -->
<LinearLayout
android:id="@+id/layout_president"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="@id/text_detail_club_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_person"
app:tint="#455A64"
android:background="@drawable/circle_edit_background"
android:backgroundTint="#ECEFF1"
android:padding="8dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PRESIDENTE:"
android:textSize="12sp"
android:textColor="#616161"/>
<TextView
android:id="@+id/text_detail_president"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="João Silva"
android:textSize="16sp"
android:textColor="#263238"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
<!-- Address Section -->
<LinearLayout
android:id="@+id/layout_address"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/layout_president"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_location"
app:tint="#455A64"
android:background="@drawable/circle_edit_background"
android:backgroundTint="#ECEFF1"
android:padding="8dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MORADA:"
android:textSize="12sp"
android:textColor="#616161"/>
<TextView
android:id="@+id/text_detail_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Rua Desportiva 123"
android:textSize="16sp"
android:textColor="#263238"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
<!-- Foundation Section -->
<LinearLayout
android:id="@+id/layout_foundation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/layout_address"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_calendar"
app:tint="#455A64"
android:background="@drawable/circle_edit_background"
android:backgroundTint="#ECEFF1"
android:padding="8dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ANO DE FUNDAÇÃO:"
android:textSize="12sp"
android:textColor="#616161"/>
<TextView
android:id="@+id/text_detail_foundation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="1995"
android:textSize="16sp"
android:textColor="#263238"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
<!-- Stadium Section (Hidden per screenshot but kept in model, or should I show it?)
The screenshot doesn't explicitly show Stadium but the code had it.
I will hide it for now to match screenshot strictly or add it if plenty space?
The user said "appears like this", implies following the screenshot.
But previously stadium was shown. I will add it as well for completeness if it fits,
or just omit if the screenshot is strict.
Screenshot: CLUBE, PRESIDENTE, MORADA, ANO DE FUNDACAO. No Stadium.
I will omit Stadium from UI to match unique request "like this".
-->
<!-- Players Button -->
<Button
android:id="@+id/btn_players"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="JOGADORES\n(Ver Lista)"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
app:cornerRadius="12dp"
android:backgroundTint="#1976D2"
app:icon="@drawable/ic_soccer"
app:iconGravity="textStart"
app:iconSize="32dp"
app:iconTint="@color/white"
android:gravity="center"
android:layout_marginTop="40dp"
app:layout_constraintTop_toBottomOf="@id/layout_foundation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="1.0"
android:layout_marginBottom="20dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F5F5"
tools:context=".ui.clubs.ClubPlayersFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_players_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/text_no_players"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sem jogadores inscritos"
android:textSize="18sp"
android:textColor="#757575"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<ProgressBar
android:id="@+id/progressBarPlayers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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_light">
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/toggleGroupEscalao"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:checkedButton="@id/btnSeniores"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:singleSelection="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/btnSeniores"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Seniores" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnJuniores"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Juniores" />
</com.google.android.material.button.MaterialButtonToggleGroup>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_clubs"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toggleGroupEscalao" />
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#ECEFF1"> android:background="@color/background_light">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -16,7 +16,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Definições" android:text="Definições"
android:textColor="#263238" android:textColor="@color/primary_color"
android:textSize="28sp" android:textSize="28sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -25,7 +25,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:text="Personaliza a aplicação de acordo com o teu gosto." android:text="Personaliza a aplicação de acordo com o teu gosto."
android:textColor="#546E7A" android:textColor="@color/text_secondary"
android:textSize="14sp" /> android:textSize="14sp" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
@@ -33,30 +33,34 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground"
app:cardCornerRadius="16dp" app:cardCornerRadius="16dp"
app:cardUseCompatPadding="true" app:cardElevation="0dp"
app:strokeColor="#CFD8DC" app:strokeColor="@color/divider"
app:strokeWidth="1dp"> app:strokeWidth="1dp"
app:cardBackgroundColor="@color/surface_card">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="18dp"> android:padding="20dp">
<ImageView <ImageView
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/menu_definicoes" android:contentDescription="@string/menu_definicoes"
android:padding="4dp" android:padding="4dp"
android:src="@android:drawable/ic_menu_manage" /> android:src="@android:drawable/ic_menu_manage"
app:tint="@color/black"/>
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:layout_marginStart="16dp"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical"> android:orientation="vertical">
@@ -64,7 +68,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Conta" android:text="Conta"
android:textColor="#263238" android:textColor="@color/black"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -72,7 +76,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Atualiza os teus dados pessoais" android:text="Atualiza os teus dados pessoais"
android:textColor="#607D8B" android:textColor="@color/text_secondary"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@@ -80,7 +84,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/menu_definicoes" android:contentDescription="@string/menu_definicoes"
android:src="@android:drawable/ic_media_next" /> android:src="@android:drawable/ic_media_next"
app:tint="@color/text_secondary"/>
</LinearLayout> </LinearLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
@@ -89,13 +94,16 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:cardCornerRadius="16dp" app:cardCornerRadius="16dp"
app:cardUseCompatPadding="true"> app:cardElevation="0dp"
app:strokeColor="@color/divider"
app:strokeWidth="1dp"
app:cardBackgroundColor="@color/surface_card">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="18dp"> android:padding="20dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -113,7 +121,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Notificações" android:text="Notificações"
android:textColor="#263238" android:textColor="@color/black"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -122,7 +130,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Ativadas" android:text="Ativadas"
android:textColor="#607D8B" android:textColor="@color/text_secondary"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@@ -136,8 +144,8 @@
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"
android:layout_marginVertical="12dp" android:layout_marginVertical="16dp"
android:background="#ECEFF1" /> android:background="@color/divider" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -155,7 +163,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Modo escuro" android:text="Modo escuro"
android:textColor="#263238" android:textColor="@color/black"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -164,7 +172,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Inativo" android:text="Inativo"
android:textColor="#607D8B" android:textColor="@color/text_secondary"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@@ -181,19 +189,22 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:cardCornerRadius="16dp" app:cardCornerRadius="16dp"
app:cardUseCompatPadding="true"> app:cardElevation="0dp"
app:strokeColor="@color/divider"
app:strokeWidth="1dp"
app:cardBackgroundColor="@color/surface_card">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="18dp"> android:padding="20dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Ajuda e suporte" android:text="Ajuda e suporte"
android:textColor="#263238" android:textColor="@color/black"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -202,20 +213,19 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:text="Consulta a nossa base de conhecimento ou fala connosco." android:text="Consulta a nossa base de conhecimento ou fala connosco."
android:textColor="#607D8B" android:textColor="@color/text_secondary"
android:textSize="14sp" /> android:textSize="14sp" />
<Button <Button
android:id="@+id/btnOpenSystemSettings" android:id="@+id/btnOpenSystemSettings"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="16dp"
android:backgroundTint="#1E88E5" android:backgroundTint="@color/black"
android:text="Abrir definições do sistema" android:text="Abrir definições do sistema"
android:textAllCaps="false" android:textAllCaps="false"
android:textColor="#FFFFFF" /> android:textColor="@color/white" />
</LinearLayout> </LinearLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -1,22 +1,27 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:background="@color/background_light"
tools:context=".ui.gallery.GalleryFragment"> tools:context=".ui.gallery.GalleryFragment">
<TextView <TextView
android:id="@+id/text_gallery"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:text="Jornadas"
android:layout_marginTop="8dp" android:textSize="24sp"
android:layout_marginEnd="8dp" android:textStyle="bold"
android:textAlignment="center" android:textColor="@color/primary_color"
android:textSize="20sp" android:layout_marginBottom="16dp" />
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" <androidx.recyclerview.widget.RecyclerView
app:layout_constraintStart_toStartOf="parent" android:id="@+id/recycler_matchdays"
app:layout_constraintTop_toTopOf="parent" /> android:layout_width="match_parent"
</androidx.constraintlayout.widget.ConstraintLayout> android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="16dp"/>
</LinearLayout>

View File

@@ -1,22 +1,80 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
android:background="@color/background_light"
tools:context=".ui.home.HomeFragment"> tools:context=".ui.home.HomeFragment">
<TextView <TextView
android:id="@+id/text_home"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:text="Classificação"
android:layout_marginTop="8dp" android:textSize="28sp"
android:layout_marginEnd="8dp" android:textStyle="bold"
android:textAlignment="center" android:textColor="@color/primary_color"
android:textSize="20sp" android:layout_marginBottom="24dp" />
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" <!-- Table Header (Clean) -->
app:layout_constraintStart_toStartOf="parent" <LinearLayout
app:layout_constraintTop_toTopOf="parent" /> android:layout_width="match_parent"
</androidx.constraintlayout.widget.ConstraintLayout> android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingVertical="12dp"
android:paddingHorizontal="4dp"
android:background="#00000000">
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:text="#"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="14sp"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Clube"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="14sp"/>
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="J"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="14sp"
android:tooltipText="Jogos" />
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Pts"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="14sp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider"
android:layout_marginBottom="8dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_standings"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:paddingTop="4dp" />
</LinearLayout>

View File

@@ -0,0 +1,201 @@
<?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_light">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Header Card -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/primary_color"
app:cardCornerRadius="24dp"
app:cardElevation="6dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<TextView
android:id="@+id/detail_game_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="65'"
android:textColor="@color/live_time"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/detail_home_team"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="Home"
android:textColor="@color/white"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/detail_score"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/detail_game_time" />
<TextView
android:id="@+id/detail_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:text="1 - 1"
android:textColor="@color/white"
android:textSize="36sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/detail_home_team"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/detail_home_team" />
<TextView
android:id="@+id/detail_away_team"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Away"
android:textColor="@color/white"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/detail_home_team"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/detail_score"
app:layout_constraintTop_toTopOf="@+id/detail_home_team" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<!-- Stats Section -->
<TextView
android:id="@+id/text_stats_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginBottom="16dp"
android:text="Estatísticas ao Vivo"
android:textColor="@color/text_primary"
android:textSize="20sp"
android:textStyle="bold" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="16dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@color/surface_card">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<!-- Possession -->
<TextView
android:id="@+id/label_possession"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Posse de Bola"
android:textColor="@color/text_secondary"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/text_possession_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50%"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:layout_marginEnd="12dp"/>
<ProgressBar
android:id="@+id/progress_possession"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="12dp"
android:layout_weight="1"
android:max="100"
android:progress="50"
android:progressDrawable="@drawable/custom_progress_bg"/>
<TextView
android:id="@+id/text_possession_away"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50%"
android:textStyle="bold"
android:textColor="@color/text_primary"
android:layout_marginStart="12dp"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider"
android:layout_marginVertical="16dp"/>
<!-- Shots -->
<TextView
android:id="@+id/label_shots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Remates"
android:textColor="@color/text_secondary"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8dp"
android:gravity="center">
<TextView
android:id="@+id/text_shots_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/secondary_color"
android:layout_marginEnd="32dp"/>
<TextView
android:id="@+id/text_shots_away"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/secondary_color"
android:layout_marginStart="32dp"/>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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_light">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_live_games"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="8dp"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_no_games"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Não há jogos ao vivo no momento"
android:textSize="16sp"
android:textColor="@color/text_secondary"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,66 @@
<?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"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="6dp"
app:cardBackgroundColor="@color/surface_card"
app:cardCornerRadius="12dp"
app:cardElevation="2dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<androidx.cardview.widget.CardView
android:id="@+id/card_logo"
android:layout_width="50dp"
android:layout_height="50dp"
app:cardCornerRadius="25dp"
app:cardElevation="0dp"
app:cardBackgroundColor="#F0F0F0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/image_club_logo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/ic_menu_gallery"
android:padding="8dp"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/text_club_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="Club Name"
android:textColor="@color/text_primary"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/text_club_stadium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/card_logo"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"/>
<TextView
android:id="@+id/text_club_stadium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="Stadium Name"
android:textColor="@color/text_secondary"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/text_club_name"
app:layout_constraintTop_toBottomOf="@+id/text_club_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,85 @@
<?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"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
app:cardBackgroundColor="@color/surface_card"
app:cardCornerRadius="16dp"
app:cardElevation="2dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp">
<TextView
android:id="@+id/text_game_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="45'"
android:textColor="@color/live_time"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/live_indicator"
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_marginEnd="6dp"
android:background="@drawable/shape_circle_live"
app:layout_constraintBottom_toBottomOf="@+id/text_game_time"
app:layout_constraintEnd_toStartOf="@+id/text_game_time"
app:layout_constraintTop_toTopOf="@+id/text_game_time" />
<TextView
android:id="@+id/text_home_team"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:text="Home Team"
android:textColor="@color/text_primary"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/text_score"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_game_time" />
<TextView
android:id="@+id/text_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:background="@drawable/shape_score_bg"
android:paddingHorizontal="16dp"
android:paddingVertical="6dp"
android:text="2 - 1"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/text_home_team"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/text_home_team" />
<TextView
android:id="@+id/text_away_team"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Away Team"
android:textColor="@color/text_primary"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/text_home_team"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/text_score"
app:layout_constraintTop_toTopOf="@+id/text_home_team" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,58 @@
<?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="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:padding="8dp">
<!-- Home Team -->
<TextView
android:id="@+id/text_home_team"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:text="Home"
android:textStyle="bold"
android:textColor="@color/text_primary" />
<!-- Score / Time -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:gravity="center"
android:orientation="vertical"
android:minWidth="60dp">
<TextView
android:id="@+id/text_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Vs"
android:textStyle="bold"
android:textColor="@color/secondary_color"
android:textSize="16sp" />
<TextView
android:id="@+id/text_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="15:00"
android:textSize="12sp"
android:textColor="@color/text_secondary" />
</LinearLayout>
<!-- Away Team -->
<TextView
android:id="@+id/text_away_team"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:text="Away"
android:textStyle="bold"
android:textColor="@color/text_primary" />
</LinearLayout>

View File

@@ -0,0 +1,39 @@
<?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"
android:layout_marginBottom="16dp"
app:cardCornerRadius="12dp"
app:cardElevation="4dp"
app:contentPadding="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Header -->
<TextView
android:id="@+id/text_matchday_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/primary_light"
android:textColor="@color/white"
android:padding="12dp"
android:text="Jornada 1"
android:textStyle="bold"
android:textSize="16sp" />
<!-- Matches List -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_matches"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
tools:itemCount="3"
tools:listitem="@layout/item_match" xmlns:tools="http://schemas.android.com/tools"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,25 @@
<?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="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:gravity="center_vertical">
<ImageView
android:id="@+id/image_player_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_menu_camera"
android:contentDescription="Player Icon"
android:layout_marginEnd="16dp"/>
<TextView
android:id="@+id/text_player_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Player Name"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>

View File

@@ -0,0 +1,59 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingVertical="16dp"
android:paddingHorizontal="4dp"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackground">
<TextView
android:id="@+id/text_position"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:text="1"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/text_team_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Team Name"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="normal" />
<TextView
android:id="@+id/text_played"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="P"
android:textColor="@color/text_secondary"
android:textSize="14sp" />
<TextView
android:id="@+id/text_points"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Pts"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="14sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#F5F5F5"/>
</LinearLayout>

View File

@@ -1,35 +1,50 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height" android:layout_height="200dp"
android:background="@drawable/side_nav_bar" android:background="@drawable/ic_header_login_bg"
android:gravity="bottom" android:gravity="top"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark"> android:theme="@style/ThemeOverlay.AppCompat.Light">
<androidx.cardview.widget.CardView
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="10dp"
app:cardCornerRadius="40dp"
app:cardBackgroundColor="@color/white"
app:cardElevation="4dp">
<ImageView <ImageView
android:id="@+id/imageView" android:id="@+id/imageView"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:contentDescription="@string/nav_header_desc" android:contentDescription="@string/nav_header_desc"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:scaleType="centerCrop"
app:srcCompat="@mipmap/ic_launcher_round" /> app:srcCompat="@mipmap/ic_launcher_round" />
</androidx.cardview.widget.CardView>
<TextView <TextView
android:id="@+id/textViewName"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:paddingTop="4dp"
android:text="@string/nav_header_title" android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold" />
<TextView <TextView
android:id="@+id/textView" android:id="@+id/textViewSubtitle"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/nav_header_subtitle" /> android:text="@string/nav_header_subtitle"
android:textColor="@color/background_light"
android:textSize="14sp" />
</LinearLayout> </LinearLayout>

View File

@@ -12,6 +12,14 @@
android:id="@+id/nav_gallery" android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery" android:icon="@drawable/ic_menu_gallery"
android:title="@string/menu_gallery" /> android:title="@string/menu_gallery" />
<item
android:id="@+id/nav_live_games"
android:icon="@android:drawable/ic_menu_view"
android:title="@string/menu_live_games" />
<item
android:id="@+id/nav_clubs"
android:icon="@android:drawable/ic_menu_my_calendar"
android:title="@string/menu_clubs" />
<item <item
android:id="@+id/nav_definicoes" android:id="@+id/nav_definicoes"
android:icon="@android:drawable/ic_menu_preferences" android:icon="@android:drawable/ic_menu_preferences"

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -22,4 +22,60 @@
android:name="com.example.vdcscore.ui.definicoes.DefinicoesFragment" android:name="com.example.vdcscore.ui.definicoes.DefinicoesFragment"
android:label="@string/menu_definicoes" android:label="@string/menu_definicoes"
tools:layout="@layout/fragment_definicoes" /> tools:layout="@layout/fragment_definicoes" />
<fragment
android:id="@+id/nav_live_games"
android:name="com.example.vdcscore.ui.livegames.LiveGamesFragment"
android:label="@string/menu_live_games"
tools:layout="@layout/fragment_live_games">
<action
android:id="@+id/action_nav_live_games_to_nav_live_game_detail"
app:destination="@id/nav_live_game_detail" />
</fragment>
<fragment
android:id="@+id/nav_live_game_detail"
android:name="com.example.vdcscore.ui.livegames.LiveGameDetailFragment"
android:label="@string/title_live_game_detail"
tools:layout="@layout/fragment_live_game_detail" />
<fragment
android:id="@+id/nav_clubs"
android:name="com.example.vdcscore.ui.clubs.ClubsFragment"
android:label="@string/menu_clubs"
tools:layout="@layout/fragment_clubs">
<action
android:id="@+id/action_nav_clubs_to_nav_club_detail"
app:destination="@id/nav_club_detail" />
</fragment>
<fragment
android:id="@+id/nav_club_detail"
android:name="com.example.vdcscore.ui.clubs.ClubDetailFragment"
android:label="Detalhes do Clube"
tools:layout="@layout/fragment_club_detail">
<argument
android:name="clubId"
app:argType="string" />
<argument
android:name="escalao"
app:argType="string" />
<action
android:id="@+id/action_nav_club_detail_to_nav_club_players"
app:destination="@id/nav_club_players" />
</fragment>
<fragment
android:id="@+id/nav_club_players"
android:name="com.example.vdcscore.ui.clubs.ClubPlayersFragment"
android:label="Jogadores"
tools:layout="@layout/fragment_club_players">
<argument
android:name="clubId"
app:argType="string" />
<argument
android:name="escalao"
app:argType="string" />
</fragment>
</navigation> </navigation>

View File

@@ -1,7 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Base.Theme.VdcScore" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Base.Theme.VdcScore" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. --> <!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> --> <!-- Force White Status Bar even in Dark Mode -->
<item name="android:statusBarColor">@color/white</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="colorPrimary">@color/primary_color</item>
<item name="colorPrimaryVariant">@color/primary_dark</item>
<item name="colorOnPrimary">@color/white</item>
<item name="colorSecondary">@color/secondary_color</item>
<item name="colorSecondaryVariant">@color/secondary_dark</item>
<item name="colorOnSecondary">@color/white</item>
</style>
<style name="Theme.VdcScore" parent="Base.Theme.VdcScore" />
<style name="Theme.VdcScore.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!-- Explicitly enforce status bar settings here too -->
<item name="android:statusBarColor">@color/white</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style> </style>
</resources> </resources>

View File

@@ -2,4 +2,27 @@
<resources> <resources>
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<!-- Minimalist Palette -->
<color name="primary_color">#000000</color> <!-- Black -->
<color name="primary_light">#404040</color> <!-- Dark Grey -->
<color name="primary_dark">#000000</color>
<color name="secondary_color">#212121</color> <!-- Dark Grey Accent -->
<color name="secondary_light">#484848</color>
<color name="secondary_dark">#000000</color>
<color name="live_indicator">#00E676</color> <!-- Bright Green (Keep for utility) -->
<color name="live_time">#FF1744</color> <!-- Red for time (Keep for utility) -->
<color name="background_light">#FFFFFF</color> <!-- Pure White Background -->
<color name="surface_light">#FFFFFF</color>
<color name="surface_card">#FFFFFF</color> <!-- White Card -->
<color name="text_primary">#212121</color> <!-- Almost Black -->
<color name="text_secondary">#757575</color> <!-- Grey -->
<color name="text_on_primary">#FFFFFF</color>
<color name="divider">#EEEEEE</color> <!-- Very light grey divider -->
<color name="input_background">#F5F5F5</color> <!-- Light grey for inputs/cards if needed -->
</resources> </resources>

View File

@@ -1,14 +1,25 @@
<resources> <resources>
<string name="app_name">VdcScore</string> <string name="app_name">VdcScore</string>
<string name="title_activity_main">MainActivity</string> <string name="title_activity_main">Classificação</string>
<string name="navigation_drawer_open">Open navigation drawer</string> <string name="navigation_drawer_open">Abrir menu</string>
<string name="navigation_drawer_close">Close navigation drawer</string> <string name="navigation_drawer_close">Fechar menu</string>
<string name="nav_header_title">Android Studio</string> <string name="nav_header_title">VdcScore</string>
<string name="nav_header_subtitle">android.studio@android.com</string> <string name="nav_header_subtitle">O teu clube</string>
<string name="nav_header_desc">Navigation header</string> <string name="nav_header_desc">Cabeçalho de navegação</string>
<string name="action_settings">Settings</string> <string name="action_settings">Definições</string>
<string name="menu_home">Home</string> <string name="menu_home">Classificação</string>
<string name="menu_gallery">Gallery</string> <string name="menu_gallery">Jornadas</string>
<string name="menu_definicoes">Definições</string> <string name="menu_definicoes">Definições</string>
<string name="menu_live_games">Jogos ao Vivo</string>
<string name="title_live_game_detail">Detalhes do Jogo</string>
<string name="menu_clubs">Clubes</string>
<!-- Profile Strings -->
<string name="change_photo_title">Alterar Foto de Perfil</string>
<string name="choose_gallery">Escolher da Galeria</string>
<string name="enter_url">Inserir URL</string>
<string name="cancel">Cancelar</string>
<string name="ok">OK</string>
<string name="url_hint">https://exemplo.com/foto.jpg</string>
</resources> </resources>

View File

@@ -1,8 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Base.Theme.VdcScore" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Base.Theme.VdcScore" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. --> <!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> --> <item name="colorPrimary">@color/primary_color</item>
<item name="colorPrimaryVariant">@color/primary_dark</item>
<item name="colorOnPrimary">@color/white</item>
<item name="colorSecondary">@color/secondary_color</item>
<item name="colorSecondaryVariant">@color/secondary_dark</item>
<item name="colorOnSecondary">@color/white</item>
<!-- Status Bar Settings -->
<item name="android:statusBarColor">@color/white</item>
<item name="android:windowLightStatusBar">true</item> <!-- Dark icons -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:textColorPrimary">@color/text_primary</item>
<item name="android:textColorSecondary">@color/text_secondary</item>
</style> </style>
<style name="Theme.VdcScore" parent="Base.Theme.VdcScore" /> <style name="Theme.VdcScore" parent="Base.Theme.VdcScore" />
@@ -10,6 +24,10 @@
<style name="Theme.VdcScore.NoActionBar"> <style name="Theme.VdcScore.NoActionBar">
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
<!-- Explicitly enforce status bar settings here too to avoid inheritance issues -->
<item name="android:statusBarColor">@color/white</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style> </style>
<style name="Theme.VdcScore.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> <style name="Theme.VdcScore.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

BIN
build_log.txt Normal file

Binary file not shown.

View File

@@ -1,5 +1,5 @@
[versions] [versions]
agp = "8.13.1" agp = "8.13.2"
junit = "4.13.2" junit = "4.13.2"
junitVersion = "1.3.0" junitVersion = "1.3.0"
espressoCore = "3.7.0" espressoCore = "3.7.0"
@@ -13,6 +13,7 @@ credentials = "1.5.0"
credentialsPlayServicesAuth = "1.5.0" credentialsPlayServicesAuth = "1.5.0"
googleid = "1.1.1" googleid = "1.1.1"
firebaseDatabase = "22.0.1" firebaseDatabase = "22.0.1"
firebaseStorage = "21.0.1"
lifecycleLivedataKtx = "2.9.4" lifecycleLivedataKtx = "2.9.4"
lifecycleViewmodelKtx = "2.9.4" lifecycleViewmodelKtx = "2.9.4"
navigationFragment = "2.9.6" navigationFragment = "2.9.6"
@@ -31,6 +32,7 @@ credentials = { group = "androidx.credentials", name = "credentials", version.re
credentials-play-services-auth = { group = "androidx.credentials", name = "credentials-play-services-auth", version.ref = "credentialsPlayServicesAuth" } credentials-play-services-auth = { group = "androidx.credentials", name = "credentials-play-services-auth", version.ref = "credentialsPlayServicesAuth" }
googleid = { group = "com.google.android.libraries.identity.googleid", name = "googleid", version.ref = "googleid" } googleid = { group = "com.google.android.libraries.identity.googleid", name = "googleid", version.ref = "googleid" }
firebase-database = { group = "com.google.firebase", name = "firebase-database", version.ref = "firebaseDatabase" } firebase-database = { group = "com.google.firebase", name = "firebase-database", version.ref = "firebaseDatabase" }
firebase-storage = { group = "com.google.firebase", name = "firebase-storage", version.ref = "firebaseStorage" }
lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" } lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" }
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" } navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" }

View File

@@ -1,4 +1,4 @@
#Wed Nov 19 10:03:29 WET 2025 #Wed Feb 25 12:48:32 WET 2026
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip