Files
PapF/app/src/main/java/com/fluxup/app/InicioFragment.java
2026-04-24 16:43:03 +01:00

406 lines
15 KiB
Java

package com.fluxup.app;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.ListenerRegistration;
import java.util.HashMap;
import java.util.Map;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.animation.BounceInterpolator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import java.util.Calendar;
import java.util.Locale;
import java.util.ArrayList;
import java.util.List;
public class InicioFragment extends Fragment {
private TextView tvTimer, tvProgressText, tvGreeting;
private FrameLayout timerBlock;
private LinearLayout tasksContainer;
private ProgressBar pbDailyTasks;
private CountDownTimer countDownTimer;
private LinearLayout progressPathContainer;
private List<View> dayNodes = new ArrayList<>();
private int currentDayIndex = 0;
private ListenerRegistration tasksListener, userListener;
private List<Task> currentTasks = new ArrayList<>();
private boolean isTimerRunning = false;
private long timeLeftInMillis = 25 * 60 * 1000; // 25 minutos
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_inicio, container, false);
tvTimer = view.findViewById(R.id.tvTimer);
tvGreeting = view.findViewById(R.id.tvGreeting);
timerBlock = view.findViewById(R.id.timerBlock);
tasksContainer = view.findViewById(R.id.tasksContainer);
tvProgressText = view.findViewById(R.id.tvProgressText);
pbDailyTasks = view.findViewById(R.id.pbDailyTasks);
progressPathContainer = view.findViewById(R.id.progressPathContainer);
progressPathContainer = view.findViewById(R.id.progressPathContainer);
initProgressPath();
startObservingTasks();
startObservingUser();
View btnStartFocus = view.findViewById(R.id.btnStartFocus);
if (btnStartFocus != null) {
btnStartFocus.setOnClickListener(v -> {
if (!isTimerRunning) {
startTimer();
((TextView)btnStartFocus).setText("Pausar Foco");
} else {
pauseTimer();
((TextView)btnStartFocus).setText("Continuar Foco");
}
});
}
view.findViewById(R.id.btnAddTasks).setOnClickListener(v -> showAddTaskDialog());
View btnStreak = view.findViewById(R.id.btnStreak);
if (btnStreak != null) {
btnStreak.setOnClickListener(v -> {
android.content.Intent intent = new android.content.Intent(getActivity(), StreakActivity.class);
startActivity(intent);
});
}
updateCountDownText();
return view;
}
private void startObservingTasks() {
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser != null) {
tasksListener = FirestoreManager.getInstance().observeTasks(currentUser.getUid(), tasks -> {
currentTasks = tasks;
updateTasksUI();
});
}
}
private void startObservingUser() {
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser != null) {
userListener = FirestoreManager.getInstance().observeUser(currentUser.getUid(), user -> {
if (tvGreeting != null) {
tvGreeting.setText("Olá, " + user.usuario + "!");
}
});
}
}
private void updateTasksUI() {
if (getContext() == null || tasksContainer == null) return;
tasksContainer.removeAllViews();
for (Task task : currentTasks) {
androidx.cardview.widget.CardView card = new androidx.cardview.widget.CardView(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(0, 0, 0, 16);
card.setLayoutParams(params);
card.setRadius(getResources().getDimension(R.dimen.radius_md));
card.setCardElevation(2f);
card.setContentPadding(16, 16, 16, 16);
LinearLayout layout = new LinearLayout(getContext());
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setGravity(android.view.Gravity.CENTER_VERTICAL);
CheckBox cb = new CheckBox(getContext());
cb.setText(task.title);
cb.setTextColor(getResources().getColor(R.color.text_primary));
cb.setTextSize(16);
cb.setChecked(task.completed);
if (task.completed) {
cb.setTextColor(getResources().getColor(R.color.success_green));
}
cb.setOnCheckedChangeListener((buttonView, isChecked) -> {
task.completed = isChecked;
FirestoreManager.getInstance().updateTask(task);
// The observer will trigger updateTasksUI again, so we don't need manual UI update here
if (isChecked) {
addXP(task.xpReward);
}
});
layout.addView(cb);
card.addView(layout);
tasksContainer.addView(card);
}
updateProgress();
}
private void addXP(int amount) {
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser != null) {
com.google.firebase.firestore.FirebaseFirestore.getInstance()
.collection("users").document(currentUser.getUid())
.update("xp", com.google.firebase.firestore.FieldValue.increment(amount));
}
}
private void updateProgress() {
int total = currentTasks.size();
int completed = 0;
for (Task task : currentTasks) {
if (task.completed) completed++;
}
if (tvProgressText != null) {
tvProgressText.setText(completed + " de " + total + " concluídos");
}
if (pbDailyTasks != null && total > 0) {
int progress = (completed * 100) / total;
pbDailyTasks.setProgress(progress);
updatePathProgress(progress);
}
}
private void initProgressPath() {
if (getContext() == null || progressPathContainer == null) return;
progressPathContainer.removeAllViews();
dayNodes.clear();
String[] days = {"SEG", "TER", "QUA", "QUI", "SEX", "SÁB", "DOM"};
String[] initials = {"S", "T", "Q", "Q", "S", "S", "D"};
// Get current day of week (Calendar.MONDAY is 2, SUNDAY is 1)
Calendar calendar = Calendar.getInstance();
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
// Map to 0-6 (Mon-Sun)
currentDayIndex = (dayOfWeek + 5) % 7;
for (int i = 0; i < 7; i++) {
View node = LayoutInflater.from(getContext()).inflate(R.layout.item_day_node, progressPathContainer, false);
View topConnector = node.findViewById(R.id.topConnector);
View bottomConnector = node.findViewById(R.id.bottomConnector);
View nodeCircle = node.findViewById(R.id.nodeCircle);
TextView nodeDayInitial = node.findViewById(R.id.nodeDayInitial);
TextView nodeDayLabel = node.findViewById(R.id.nodeDayLabel);
ProgressBar nodeProgress = node.findViewById(R.id.nodeProgress);
nodeDayLabel.setText(days[i]);
nodeDayInitial.setText(initials[i]);
// Hide connectors at ends
if (i == 0) topConnector.setVisibility(View.INVISIBLE);
if (i == 6) bottomConnector.setVisibility(View.INVISIBLE);
// Style based on state
if (i < currentDayIndex) {
// Past day - Assume completed for demo
nodeCircle.setBackgroundResource(R.drawable.node_circle_bg);
nodeCircle.getBackground().setTint(getResources().getColor(R.color.success_green));
nodeDayInitial.setTextColor(getResources().getColor(R.color.white));
nodeProgress.setVisibility(View.GONE);
} else if (i == currentDayIndex) {
// Today
nodeCircle.setBackgroundResource(R.drawable.node_circle_bg);
nodeCircle.getBackground().setTint(getResources().getColor(R.color.primary_purple));
nodeDayInitial.setTextColor(getResources().getColor(R.color.white));
nodeDayLabel.setTextColor(getResources().getColor(R.color.primary_purple));
nodeProgress.setVisibility(View.VISIBLE);
} else {
// Future
node.setAlpha(0.4f);
nodeProgress.setVisibility(View.GONE);
}
dayNodes.add(node);
progressPathContainer.addView(node);
}
}
private void updatePathProgress(int progress) {
if (currentDayIndex >= dayNodes.size()) return;
View todayNode = dayNodes.get(currentDayIndex);
ProgressBar nodeProgress = todayNode.findViewById(R.id.nodeProgress);
View nodeCircle = todayNode.findViewById(R.id.nodeCircle);
TextView nodeDayInitial = todayNode.findViewById(R.id.nodeDayInitial);
if (nodeProgress != null) {
nodeProgress.setProgress(progress);
}
if (progress == 100) {
// Task completion animation
nodeCircle.getBackground().setTint(getResources().getColor(R.color.success_green));
triggerSuccessAnimation(todayNode);
} else {
nodeCircle.getBackground().setTint(getResources().getColor(R.color.primary_purple));
}
}
private void triggerSuccessAnimation(View view) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.2f, 1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.2f, 1f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.setInterpolator(new BounceInterpolator());
animatorSet.playTogether(scaleX, scaleY);
animatorSet.start();
Toast.makeText(getContext(), "Dia Completado! 🎉", Toast.LENGTH_SHORT).show();
}
private void startTimer() {
countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
@Override
public void onTick(long millisUntilFinished) {
timeLeftInMillis = millisUntilFinished;
updateCountDownText();
}
@Override
public void onFinish() {
isTimerRunning = false;
if(getContext() != null) {
Toast.makeText(getContext(), "Foco concluído! +50 XP", Toast.LENGTH_LONG).show();
addXP(50);
}
}
}.start();
isTimerRunning = true;
}
private void pauseTimer() {
if (countDownTimer != null) {
countDownTimer.cancel();
}
isTimerRunning = false;
}
private void updateCountDownText() {
int minutes = (int) (timeLeftInMillis / 1000) / 60;
int seconds = (int) (timeLeftInMillis / 1000) % 60;
String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
if(tvTimer != null) tvTimer.setText(timeLeftFormatted);
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (tasksListener != null) {
tasksListener.remove();
}
if (userListener != null) {
userListener.remove();
}
pauseTimer(); // Parar o timer se a view for destruída
}
private void showAddTaskDialog() {
if (getContext() == null) return;
// Build input field
android.widget.EditText editText = new android.widget.EditText(getContext());
editText.setHint("Escreve o teu desafio…");
editText.setInputType(android.text.InputType.TYPE_CLASS_TEXT
| android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
editText.setTextSize(16);
editText.setSingleLine(false);
editText.setMaxLines(3);
// Wrap with padding
android.widget.FrameLayout container = new android.widget.FrameLayout(getContext());
android.widget.FrameLayout.LayoutParams lp = new android.widget.FrameLayout.LayoutParams(
android.widget.FrameLayout.LayoutParams.MATCH_PARENT,
android.widget.FrameLayout.LayoutParams.WRAP_CONTENT);
int dp24 = (int) (24 * getResources().getDisplayMetrics().density);
lp.setMargins(dp24, dp24 / 2, dp24, 0);
editText.setLayoutParams(lp);
container.addView(editText);
androidx.appcompat.app.AlertDialog dialog = new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
.setTitle("Novo Desafio")
.setView(container)
.setNegativeButton("Cancelar", null)
.setPositiveButton("Adicionar", null)
.create();
dialog.setOnShowListener(d -> {
// Style buttons
android.widget.Button btnAdd = dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE);
android.widget.Button btnCancel = dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_NEGATIVE);
if (btnAdd != null) btnAdd.setTextColor(getResources().getColor(R.color.primary_purple));
if (btnCancel != null) btnCancel.setTextColor(getResources().getColor(R.color.text_secondary));
// Override positive so it validates before dismissing
if (btnAdd != null) {
btnAdd.setOnClickListener(v -> {
String title = editText.getText().toString().trim();
if (title.isEmpty()) {
editText.setError("Escreve um desafio");
return;
}
saveNewTask(title);
dialog.dismiss();
});
}
editText.requestFocus();
if (dialog.getWindow() != null) {
dialog.getWindow().setSoftInputMode(
android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
});
dialog.show();
}
private void saveNewTask(String title) {
com.google.firebase.auth.FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
if (currentUser == null) return;
String uid = currentUser.getUid();
String taskId = com.google.firebase.firestore.FirebaseFirestore.getInstance()
.collection("tasks").document().getId();
Task task = new Task(taskId, title, 10, uid);
FirestoreManager.getInstance().addTask(task);
}
}