1077 lines
47 KiB
Java
1077 lines
47 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 android.widget.Button;
|
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
|
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;
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
|
|
public class InicioFragment extends Fragment {
|
|
|
|
// Focus Mode
|
|
private enum FocusState { NOT_STARTED, RUNNING, PAUSED }
|
|
private FocusState currentFocusState = FocusState.NOT_STARTED;
|
|
|
|
private TextView tvTimer, tvGreeting, tvMotivationalSubtitle, tvFocusStatus, tvFocusTitle;
|
|
private TextView tvTodayStreak, tvTodayXP, tvTodayTasksCount, tvNoTasksIncentive;
|
|
private TextView tvDailyRewardGoal;
|
|
private ProgressBar pbDailyTasksProgress;
|
|
private androidx.recyclerview.widget.RecyclerView rvTasks;
|
|
private TasksAdapter tasksAdapter;
|
|
private LinearLayout miniRankingContainer, layoutTasksSection;
|
|
private Button btnStartFocus, btnSecondaryFocus, btnAddTasks, btnClaimReward;
|
|
private androidx.cardview.widget.CardView btnStreakPage;
|
|
|
|
private CountDownTimer countDownTimer;
|
|
private LinearLayout progressPathContainer;
|
|
private List<View> dayNodes = new ArrayList<>();
|
|
private int currentDayIndex = 0;
|
|
private ListenerRegistration tasksListener, userListener, rankingListener;
|
|
private List<Task> currentTasks = new ArrayList<>();
|
|
private Task selectedTaskForFocus = null;
|
|
private boolean isCompletingFocus = false;
|
|
|
|
private boolean isTimerRunning = false;
|
|
private long timeLeftInMillis = 25 * 60 * 1000; // 25 minutos
|
|
|
|
private String[] motivationalQuotes = {
|
|
"Pronto para vencer hoje?",
|
|
"Só precisas de começar.",
|
|
"Um passo de cada vez.",
|
|
"A consistência é a chave.",
|
|
"Foca no progresso, não na perfeição.",
|
|
"Hoje é um ótimo dia para ser produtivo!",
|
|
"Vence a procrastinação agora.",
|
|
"A tua versão do futuro vai agradecer.",
|
|
"Pequenos passos, grandes resultados."
|
|
};
|
|
|
|
|
|
@Nullable
|
|
@Override
|
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
|
View view = inflater.inflate(R.layout.fragment_inicio, container, false);
|
|
|
|
// Header
|
|
tvGreeting = view.findViewById(R.id.tvGreeting);
|
|
tvMotivationalSubtitle = view.findViewById(R.id.tvMotivationalSubtitle);
|
|
view.findViewById(R.id.cardProfileAvatar).setOnClickListener(v -> {
|
|
if (getActivity() instanceof MainActivity) {
|
|
BottomNavigationView nav = ((MainActivity) getActivity()).findViewById(R.id.bottom_navigation);
|
|
if (nav != null) {
|
|
nav.setSelectedItemId(R.id.nav_profile);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Today Card
|
|
tvTodayStreak = view.findViewById(R.id.tvTodayStreak);
|
|
tvTodayXP = view.findViewById(R.id.tvTodayXP);
|
|
tvTodayTasksCount = view.findViewById(R.id.tvTodayTasksCount);
|
|
pbDailyTasksProgress = view.findViewById(R.id.pbDailyTasksProgress);
|
|
|
|
// Tasks
|
|
layoutTasksSection = view.findViewById(R.id.layoutTasksSection);
|
|
rvTasks = view.findViewById(R.id.rvTasks);
|
|
rvTasks.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(getContext()));
|
|
tasksAdapter = new TasksAdapter(currentTasks, new TasksAdapter.OnTaskClickListener() {
|
|
@Override public void onTaskFocus(Task task) { selectTaskForFocus(task); }
|
|
@Override public void onTaskDelete(Task task) { showDeleteConfirmDialog(task); }
|
|
@Override public void onTaskEdit(Task task) { showEditTaskDialog(task); }
|
|
});
|
|
rvTasks.setAdapter(tasksAdapter);
|
|
setupSwipeToDelete();
|
|
|
|
tvNoTasksIncentive = view.findViewById(R.id.tvNoTasksIncentive);
|
|
btnAddTasks = view.findViewById(R.id.btnAddTasks);
|
|
btnAddTasks.setOnClickListener(v -> showAddTaskDialog());
|
|
|
|
// Focus Mode
|
|
tvTimer = view.findViewById(R.id.tvTimer);
|
|
tvFocusStatus = view.findViewById(R.id.tvFocusStatus);
|
|
tvFocusTitle = view.findViewById(R.id.tvFocusTitle);
|
|
btnStartFocus = view.findViewById(R.id.btnStartFocus);
|
|
btnSecondaryFocus = view.findViewById(R.id.btnSecondaryFocus);
|
|
|
|
btnStartFocus.setOnClickListener(v -> handleStartFocusClick());
|
|
btnSecondaryFocus.setOnClickListener(v -> handleSecondaryFocusClick());
|
|
|
|
// Progress
|
|
progressPathContainer = view.findViewById(R.id.progressPathContainer);
|
|
|
|
// Mini Ranking
|
|
miniRankingContainer = view.findViewById(R.id.miniRankingContainer);
|
|
view.findViewById(R.id.btnViewFullRanking).setOnClickListener(v -> {
|
|
startActivity(new android.content.Intent(getActivity(), TrophiesActivity.class));
|
|
});
|
|
|
|
// Reward
|
|
tvDailyRewardGoal = view.findViewById(R.id.tvDailyRewardGoal);
|
|
btnClaimReward = view.findViewById(R.id.btnClaimReward);
|
|
btnClaimReward.setOnClickListener(v -> claimDailyReward());
|
|
|
|
// Streak Page
|
|
btnStreakPage = view.findViewById(R.id.btnStreakPage);
|
|
btnStreakPage.setOnClickListener(v -> {
|
|
startActivity(new android.content.Intent(getActivity(), StreakActivity.class));
|
|
});
|
|
|
|
setRandomMotivationalQuote();
|
|
initProgressPath();
|
|
startObservingTasks();
|
|
startObservingUser();
|
|
startObservingRanking();
|
|
|
|
updateCountDownText();
|
|
|
|
return view;
|
|
}
|
|
|
|
private void setRandomMotivationalQuote() {
|
|
int index = (int) (Math.random() * motivationalQuotes.length);
|
|
if (tvMotivationalSubtitle != null) {
|
|
tvMotivationalSubtitle.setText(motivationalQuotes[index]);
|
|
}
|
|
}
|
|
|
|
private void startObservingTasks() {
|
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
|
if (currentUser != null) {
|
|
tasksListener = FirestoreManager.getInstance().observeTasks(currentUser.getUid(), tasks -> {
|
|
List<Task> activeTasks = new ArrayList<>();
|
|
for (Task t : tasks) {
|
|
if (!t.completed) activeTasks.add(t);
|
|
}
|
|
currentTasks = activeTasks;
|
|
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 + "!");
|
|
}
|
|
if (tvTodayStreak != null) {
|
|
syncDailyStreak(user);
|
|
}
|
|
refreshTodayStats(user);
|
|
|
|
// Update Reward Button State
|
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new java.util.Date());
|
|
boolean alreadyClaimed = today.equals(user.last_reward_claim_date);
|
|
|
|
if (user.tasks_concluidas_hoje >= user.meta_diaria_tarefas && !alreadyClaimed) {
|
|
btnClaimReward.setEnabled(true);
|
|
btnClaimReward.setAlpha(1.0f);
|
|
btnClaimReward.setText("Resgatar");
|
|
} else if (alreadyClaimed) {
|
|
btnClaimReward.setEnabled(false);
|
|
btnClaimReward.setAlpha(0.5f);
|
|
btnClaimReward.setText("Resgatado");
|
|
} else {
|
|
btnClaimReward.setEnabled(false);
|
|
btnClaimReward.setAlpha(0.5f);
|
|
btnClaimReward.setText("Resgatar");
|
|
}
|
|
|
|
updateTodayCard(user);
|
|
checkDailyResetAndStreak(user);
|
|
loadWeeklyProgress(user);
|
|
});
|
|
}
|
|
}
|
|
|
|
private void loadWeeklyProgress(Usuario user) {
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
cal.set(Calendar.MINUTE, 0);
|
|
cal.set(Calendar.SECOND, 0);
|
|
cal.set(Calendar.MILLISECOND, 0);
|
|
|
|
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1 = Sunday, 2 = Monday
|
|
int daysToSubtract = (dayOfWeek + 5) % 7; // Monday = 0, Sunday = 6
|
|
|
|
Calendar startCal = (Calendar) cal.clone();
|
|
startCal.add(Calendar.DAY_OF_YEAR, -daysToSubtract);
|
|
java.util.Date startDate = startCal.getTime();
|
|
|
|
Calendar endCal = (Calendar) startCal.clone();
|
|
endCal.add(Calendar.DAY_OF_YEAR, 7);
|
|
java.util.Date endDate = endCal.getTime();
|
|
|
|
android.util.Log.d("FLUXUP_DEBUG", "CURRENT_WEEK_RANGE: " + startDate + " to " + endDate);
|
|
|
|
FirestoreManager.getInstance().getDailyProgress(user.id_usuario, startDate, endDate, user.meta_diaria_tarefas > 0 ? user.meta_diaria_tarefas : 3, progressMap -> {
|
|
if (!isAdded()) return;
|
|
|
|
String todayStr = new java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault()).format(new java.util.Date());
|
|
DailyProgress dpToday = progressMap.get(todayStr);
|
|
android.util.Log.d("FLUXUP_DEBUG", "HOME_TODAY_COMPLETED_TASKS: " + (dpToday != null ? dpToday.completedTasks : 0));
|
|
|
|
android.util.Log.d("FLUXUP_DEBUG", "HOME_PROGRESS_DATA: " + progressMap.size());
|
|
updateProgressPath(progressMap);
|
|
});
|
|
}
|
|
|
|
private void updateTasksUI() {
|
|
if (tasksAdapter != null) {
|
|
tasksAdapter.setTasks(currentTasks);
|
|
}
|
|
refreshTodayStats();
|
|
}
|
|
|
|
private void refreshTodayStats() {
|
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
|
if (currentUser == null) return;
|
|
FirestoreManager.getInstance().getUser(currentUser.getUid(), this::refreshTodayStats);
|
|
}
|
|
|
|
private void refreshTodayStats(Usuario user) {
|
|
if (user == null || !isAdded()) return;
|
|
|
|
// Update basic card info (Tasks, Progress)
|
|
updateTodayCard(user);
|
|
|
|
// Update XP specifically from logs
|
|
FirestoreManager.getInstance().getTodayXp(user.id_usuario, todayXp -> {
|
|
if (isAdded() && tvTodayXP != null) {
|
|
tvTodayXP.setText(String.valueOf(todayXp));
|
|
android.util.Log.d("FLUXUP_DEBUG", "XP_STATE_UPDATED: " + todayXp);
|
|
android.util.Log.d("FLUXUP_DEBUG", "XP_VALUE_RENDERED_IN_CARD: " + todayXp);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void selectTaskForFocus(Task task) {
|
|
selectedTaskForFocus = task;
|
|
timeLeftInMillis = task.duration * 60 * 1000;
|
|
updateCountDownText();
|
|
updateFocusUI(FocusState.NOT_STARTED);
|
|
if (tvFocusTitle != null) {
|
|
tvFocusTitle.setText(task.title);
|
|
}
|
|
if (getContext() != null) {
|
|
Toast.makeText(getContext(), "Tarefa selecionada: " + task.title, Toast.LENGTH_SHORT).show();
|
|
}
|
|
}
|
|
|
|
private void setupSwipeToDelete() {
|
|
new androidx.recyclerview.widget.ItemTouchHelper(new androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback(0, androidx.recyclerview.widget.ItemTouchHelper.LEFT | androidx.recyclerview.widget.ItemTouchHelper.RIGHT) {
|
|
@Override
|
|
public boolean onMove(@NonNull androidx.recyclerview.widget.RecyclerView recyclerView, @NonNull androidx.recyclerview.widget.RecyclerView.ViewHolder viewHolder, @NonNull androidx.recyclerview.widget.RecyclerView.ViewHolder target) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onSwiped(@NonNull androidx.recyclerview.widget.RecyclerView.ViewHolder viewHolder, int direction) {
|
|
int position = viewHolder.getAdapterPosition();
|
|
Task task = currentTasks.get(position);
|
|
showDeleteConfirmDialog(task);
|
|
tasksAdapter.notifyItemChanged(position); // Revert swipe if canceled? Firestore update will refresh anyway.
|
|
}
|
|
}).attachToRecyclerView(rvTasks);
|
|
}
|
|
|
|
private void addXP(int amount) {
|
|
if (!isAdded()) return;
|
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
|
if (currentUser != null) {
|
|
String uid = currentUser.getUid();
|
|
Map<String, Object> updates = new HashMap<>();
|
|
updates.put("xp", com.google.firebase.firestore.FieldValue.increment(amount));
|
|
updates.put("xp_hoje", com.google.firebase.firestore.FieldValue.increment(amount));
|
|
updates.put("xp_semanal", com.google.firebase.firestore.FieldValue.increment(amount));
|
|
|
|
FirestoreManager.getInstance().addXpLog(uid, amount, "bonus");
|
|
|
|
FirestoreManager.getInstance().getUser(uid, user -> {
|
|
if (user != null && isAdded()) {
|
|
int currentLevel = user.level;
|
|
int threshold = (currentLevel * (currentLevel + 1) / 2) * 100;
|
|
if (user.xp + amount >= threshold) {
|
|
updates.put("level", currentLevel + 1);
|
|
showLevelUpAnimation(currentLevel + 1);
|
|
}
|
|
FirestoreManager.getInstance().updateUserStats(uid, updates);
|
|
refreshTodayStats();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private void updateTodayCard() {
|
|
refreshTodayStats();
|
|
}
|
|
|
|
private void syncDailyStreak(Usuario user) {
|
|
if (user == null) return;
|
|
|
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault()).format(new java.util.Date());
|
|
int completedTasksToday = user.tasks_concluidas_hoje;
|
|
int dailyTaskGoal = user.meta_diaria_tarefas > 0 ? user.meta_diaria_tarefas : 3;
|
|
int currentStreak = user.streak;
|
|
String lastStreakDate = user.last_streak_completed_date;
|
|
|
|
boolean willIncrement = (completedTasksToday >= dailyTaskGoal) && !today.equals(lastStreakDate);
|
|
int displayedStreak = 0;
|
|
|
|
if (completedTasksToday < dailyTaskGoal) {
|
|
displayedStreak = 0;
|
|
} else {
|
|
if (willIncrement) {
|
|
int newStreak = Math.max(currentStreak, 0) + 1;
|
|
displayedStreak = newStreak;
|
|
|
|
// Salvar no backend
|
|
Map<String, Object> updates = new HashMap<>();
|
|
updates.put("streak", newStreak);
|
|
updates.put("last_streak_completed_date", today);
|
|
if (newStreak > user.melhor_streak) {
|
|
updates.put("melhor_streak", newStreak);
|
|
}
|
|
FirestoreManager.getInstance().updateUserStats(user.id_usuario, updates);
|
|
|
|
// Atualizar objeto local para evitar loops ou UI atrasada
|
|
user.streak = newStreak;
|
|
user.last_streak_completed_date = today;
|
|
} else {
|
|
displayedStreak = currentStreak;
|
|
}
|
|
}
|
|
|
|
// Debug Logs solicitados
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "--- syncDailyStreak ---");
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "completedTasksToday = " + completedTasksToday);
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "dailyTaskGoal = " + dailyTaskGoal);
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "currentStreak = " + currentStreak);
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "lastStreakDate = " + lastStreakDate);
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "today = " + today);
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "willIncrement = " + willIncrement);
|
|
android.util.Log.d("FLUXUP_STREAK_DEBUG", "displayedStreak = " + displayedStreak);
|
|
|
|
if (tvTodayStreak != null) {
|
|
tvTodayStreak.setText(displayedStreak + " dias");
|
|
}
|
|
}
|
|
|
|
private void updateTodayCard(Usuario user) {
|
|
if (user == null) return;
|
|
int completed = user.tasks_concluidas_hoje;
|
|
int goal = user.meta_diaria_tarefas;
|
|
if (goal <= 0) goal = 3; // Default fallback
|
|
|
|
// Sincronizar e mostrar streak
|
|
syncDailyStreak(user);
|
|
|
|
if (tvTodayTasksCount != null) {
|
|
tvTodayTasksCount.setText(completed + "/" + goal);
|
|
}
|
|
|
|
if (pbDailyTasksProgress != null && goal > 0) {
|
|
int progress = (completed * 100) / goal;
|
|
if (progress > 100) progress = 100;
|
|
pbDailyTasksProgress.setProgress(progress);
|
|
updatePathProgress(progress);
|
|
}
|
|
|
|
if (currentTasks != null && tvNoTasksIncentive != null && layoutTasksSection != null) {
|
|
if (currentTasks.isEmpty()) {
|
|
tvNoTasksIncentive.setVisibility(View.VISIBLE);
|
|
layoutTasksSection.setVisibility(View.GONE);
|
|
} else {
|
|
tvNoTasksIncentive.setVisibility(View.GONE);
|
|
layoutTasksSection.setVisibility(View.VISIBLE);
|
|
}
|
|
}
|
|
|
|
if (tasksAdapter != null) {
|
|
tasksAdapter.setTasks(currentTasks);
|
|
}
|
|
}
|
|
|
|
private void checkDailyResetAndStreak(Usuario user) {
|
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new java.util.Date());
|
|
if (!today.equals(user.last_active_date)) {
|
|
Map<String, Object> updates = new HashMap<>();
|
|
|
|
// Streak logic
|
|
if (!user.last_active_date.isEmpty()) {
|
|
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
|
try {
|
|
java.util.Date lastDate = sdf.parse(user.last_active_date);
|
|
java.util.Date todayDate = sdf.parse(today);
|
|
long diff = (todayDate.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24);
|
|
|
|
if (diff == 1) {
|
|
// Successive day, but wait for first task completion to increment streak?
|
|
// Or increment now if they at least logged in? User said "Completar pelo menos 1 tarefa por dia -> streak +1"
|
|
// So we don't increment here, we just check if we should reset.
|
|
} else if (diff > 1) {
|
|
// Failed a day
|
|
updates.put("streak", 0);
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
updates.put("xp_hoje", 0);
|
|
updates.put("tasks_concluidas_hoje", 0);
|
|
updates.put("tempo_foco_hoje", 0);
|
|
updates.put("last_active_date", today);
|
|
FirestoreManager.getInstance().updateUserStats(user.id_usuario, updates);
|
|
|
|
// Login reward
|
|
addXP(10);
|
|
if (getContext() != null) {
|
|
Toast.makeText(getContext(), "Recompensa de login: +10 XP!", Toast.LENGTH_SHORT).show();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void startObservingRanking() {
|
|
rankingListener = com.google.firebase.firestore.FirebaseFirestore.getInstance()
|
|
.collection("users")
|
|
.orderBy("xp_hoje", com.google.firebase.firestore.Query.Direction.DESCENDING)
|
|
.limit(3)
|
|
.addSnapshotListener((snapshots, e) -> {
|
|
if (e != null || snapshots == null) return;
|
|
miniRankingContainer.removeAllViews();
|
|
int rank = 1;
|
|
for (com.google.firebase.firestore.DocumentSnapshot doc : snapshots.getDocuments()) {
|
|
Usuario u = doc.toObject(Usuario.class);
|
|
if (u != null) {
|
|
addMiniRankingItem(rank++, u.usuario, u.xp_hoje);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private void addMiniRankingItem(int rank, String name, int xp) {
|
|
if (getContext() == null || miniRankingContainer == null) return;
|
|
|
|
View item = getLayoutInflater().inflate(R.layout.item_ranking_user, miniRankingContainer, false);
|
|
TextView tvRank = item.findViewById(R.id.tvRankPosition);
|
|
TextView tvName = item.findViewById(R.id.tvRankingName);
|
|
TextView tvXP = item.findViewById(R.id.tvRankingXP);
|
|
|
|
tvRank.setText("#" + rank);
|
|
tvName.setText(name);
|
|
tvXP.setText(xp + " XP");
|
|
|
|
// Remove elevation for mini ranking to keep it clean
|
|
if (item instanceof androidx.cardview.widget.CardView) {
|
|
((androidx.cardview.widget.CardView) item).setCardElevation(0);
|
|
((androidx.cardview.widget.CardView) item).setCardBackgroundColor(android.graphics.Color.TRANSPARENT);
|
|
}
|
|
|
|
miniRankingContainer.addView(item);
|
|
}
|
|
|
|
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 leftConnector = node.findViewById(R.id.leftConnector);
|
|
View rightConnector = node.findViewById(R.id.rightConnector);
|
|
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) leftConnector.setVisibility(View.INVISIBLE);
|
|
if (i == 6) rightConnector.setVisibility(View.INVISIBLE);
|
|
|
|
// Default empty state
|
|
nodeCircle.setBackgroundResource(R.drawable.node_circle_bg);
|
|
if (getContext() != null) {
|
|
nodeCircle.getBackground().setTint(android.graphics.Color.parseColor("#E0E0E0"));
|
|
nodeDayInitial.setTextColor(ContextCompat.getColor(getContext(), R.color.text_secondary));
|
|
nodeDayLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.text_secondary));
|
|
}
|
|
nodeProgress.setVisibility(View.GONE);
|
|
|
|
dayNodes.add(node);
|
|
progressPathContainer.addView(node);
|
|
}
|
|
}
|
|
|
|
private void updateProgressPath(Map<String, DailyProgress> progressMap) {
|
|
if (getContext() == null || dayNodes == null || dayNodes.isEmpty()) return;
|
|
|
|
Calendar cal = Calendar.getInstance();
|
|
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
cal.set(Calendar.MINUTE, 0);
|
|
cal.set(Calendar.SECOND, 0);
|
|
cal.set(Calendar.MILLISECOND, 0);
|
|
|
|
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
|
|
int daysToSubtract = (dayOfWeek + 5) % 7;
|
|
|
|
Calendar startCal = (Calendar) cal.clone();
|
|
startCal.add(Calendar.DAY_OF_YEAR, -daysToSubtract);
|
|
|
|
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
|
|
|
for (int i = 0; i < 7; i++) {
|
|
Calendar dayCal = (Calendar) startCal.clone();
|
|
dayCal.add(Calendar.DAY_OF_YEAR, i);
|
|
String dateStr = sdf.format(dayCal.getTime());
|
|
DailyProgress dp = progressMap.get(dateStr);
|
|
|
|
View node = dayNodes.get(i);
|
|
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);
|
|
View rightConnector = node.findViewById(R.id.rightConnector);
|
|
|
|
if (dp != null && "complete".equals(dp.status)) {
|
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), R.color.success_green));
|
|
nodeDayInitial.setTextColor(ContextCompat.getColor(getContext(), R.color.white));
|
|
} else if (dp != null && "partial".equals(dp.status)) {
|
|
nodeCircle.getBackground().setTint(android.graphics.Color.parseColor("#4FC3F7"));
|
|
nodeDayInitial.setTextColor(ContextCompat.getColor(getContext(), R.color.white));
|
|
} else {
|
|
nodeCircle.getBackground().setTint(android.graphics.Color.parseColor("#E0E0E0"));
|
|
nodeDayInitial.setTextColor(ContextCompat.getColor(getContext(), R.color.text_primary));
|
|
}
|
|
|
|
// Streak connector color logic
|
|
if (i < 6) {
|
|
Calendar nextDayCal = (Calendar) dayCal.clone();
|
|
nextDayCal.add(Calendar.DAY_OF_YEAR, 1);
|
|
DailyProgress nextDp = progressMap.get(sdf.format(nextDayCal.getTime()));
|
|
if (dp != null && "complete".equals(dp.status) && nextDp != null && "complete".equals(nextDp.status)) {
|
|
rightConnector.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.success_green));
|
|
} else {
|
|
rightConnector.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.border_color));
|
|
}
|
|
}
|
|
|
|
if (i == currentDayIndex) {
|
|
nodeDayLabel.setVisibility(View.VISIBLE);
|
|
nodeDayLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.primary_purple));
|
|
|
|
if (dp == null || !"complete".equals(dp.status)) {
|
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), R.color.primary_purple));
|
|
nodeDayInitial.setTextColor(ContextCompat.getColor(getContext(), R.color.white));
|
|
}
|
|
nodeProgress.setVisibility(View.VISIBLE);
|
|
if (dp != null && dp.dailyGoal > 0) {
|
|
nodeProgress.setProgress(dp.completedTasks * 100 / dp.dailyGoal);
|
|
} else {
|
|
nodeProgress.setProgress(0);
|
|
}
|
|
} else {
|
|
nodeDayLabel.setVisibility(View.GONE);
|
|
nodeProgress.setVisibility(View.GONE);
|
|
}
|
|
|
|
if (i > currentDayIndex) {
|
|
node.setAlpha(0.4f);
|
|
} else {
|
|
node.setAlpha(1.0f);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void completeTask(Task task) {
|
|
task.completed = true;
|
|
FirestoreManager.getInstance().updateTask(task);
|
|
updateUserTaskCount();
|
|
triggerVibration();
|
|
}
|
|
|
|
private void updateUserTaskCount() {
|
|
if (!isAdded()) return;
|
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
|
if (currentUser != null) {
|
|
String uid = currentUser.getUid();
|
|
FirestoreManager.getInstance().getUser(uid, user -> {
|
|
if (user != null && isAdded()) {
|
|
Map<String, Object> updates = new HashMap<>();
|
|
updates.put("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
|
|
updates.put("total_tasks_concluidas", com.google.firebase.firestore.FieldValue.increment(1));
|
|
|
|
// Adicionar log de XP mesmo em manual para permitir recálculo se necessário
|
|
FirestoreManager.getInstance().addXpLog(uid, 0, "task_manual_completion");
|
|
|
|
FirestoreManager.getInstance().updateUserStats(uid, updates, () -> {
|
|
if (isAdded()) refreshTodayStats();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private void showLevelUpAnimation(int newLevel) {
|
|
if (getContext() == null) return;
|
|
View dialogView = getLayoutInflater().inflate(R.layout.dialog_level_up, null);
|
|
TextView tvNewLevel = dialogView.findViewById(R.id.tvNewLevel);
|
|
tvNewLevel.setText(String.valueOf(newLevel));
|
|
|
|
androidx.appcompat.app.AlertDialog dialog = new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
|
.setView(dialogView)
|
|
.setPositiveButton("Incrível!", null)
|
|
.create();
|
|
|
|
dialog.show();
|
|
triggerVibration();
|
|
NotificationHelper.showNotification(getContext(), "🎉 SUBISTE DE NÍVEL!", "Chegaste ao nível " + newLevel + "! Continua assim.");
|
|
}
|
|
|
|
private void showXpPopup(String text) {
|
|
if (getContext() != null) {
|
|
Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
|
|
}
|
|
}
|
|
|
|
private void triggerVibration() {
|
|
if (getContext() == null) return;
|
|
|
|
try {
|
|
// Check settings
|
|
android.content.SharedPreferences prefs = getContext().getSharedPreferences("FluxupSettings", android.content.Context.MODE_PRIVATE);
|
|
boolean vibrationEnabled = prefs.getBoolean("vibration_on_finish", true);
|
|
|
|
if (!vibrationEnabled) {
|
|
android.util.Log.d("FLUXUP_DEBUG", "VIBRATION_DISABLED_BY_USER");
|
|
return;
|
|
}
|
|
|
|
android.os.Vibrator v = (android.os.Vibrator) getContext().getSystemService(android.content.Context.VIBRATOR_SERVICE);
|
|
if (v != null && v.hasVibrator()) {
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
|
v.vibrate(android.os.VibrationEffect.createOneShot(100, android.os.VibrationEffect.DEFAULT_AMPLITUDE));
|
|
} else {
|
|
v.vibrate(100);
|
|
}
|
|
android.util.Log.d("FLUXUP_DEBUG", "VIBRATION_SUCCESS");
|
|
}
|
|
} catch (Exception e) {
|
|
android.util.Log.e("FLUXUP_DEBUG", "VIBRATION_ERROR: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private void claimDailyReward() {
|
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
|
if (currentUser != null) {
|
|
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new java.util.Date());
|
|
Map<String, Object> updates = new HashMap<>();
|
|
updates.put("last_reward_claim_date", today);
|
|
FirestoreManager.getInstance().updateUserStats(currentUser.getUid(), updates);
|
|
addXP(100);
|
|
|
|
btnClaimReward.setEnabled(false);
|
|
btnClaimReward.setText("Resgatado");
|
|
btnClaimReward.setAlpha(0.5f);
|
|
|
|
if (getContext() != null) {
|
|
Toast.makeText(getContext(), "Recompensa diária resgatada! +100 XP", Toast.LENGTH_LONG).show();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void showDeleteConfirmDialog(Task task) {
|
|
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
|
.setTitle("Eliminar Tarefa")
|
|
.setMessage("Tens a certeza que queres eliminar esta tarefa?")
|
|
.setNegativeButton("Cancelar", null)
|
|
.setPositiveButton("Eliminar", (dialog, which) -> {
|
|
FirestoreManager.getInstance().deleteTask(task.id);
|
|
})
|
|
.show();
|
|
}
|
|
|
|
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);
|
|
if (nodeProgress != null) nodeProgress.setProgress(progress);
|
|
if (progress == 100 && getContext() != null) {
|
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), R.color.success_green));
|
|
triggerSuccessAnimation(todayNode);
|
|
} else if (getContext() != null) {
|
|
nodeCircle.getBackground().setTint(ContextCompat.getColor(getContext(), 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();
|
|
|
|
if (getContext() != null) {
|
|
Toast.makeText(getContext(), "Dia Completado! 🎉", Toast.LENGTH_SHORT).show();
|
|
}
|
|
}
|
|
|
|
|
|
private void handleStartFocusClick() {
|
|
if (currentFocusState == FocusState.NOT_STARTED) {
|
|
if (selectedTaskForFocus == null) {
|
|
if (getContext() != null) Toast.makeText(getContext(), "Seleciona uma tarefa primeiro!", Toast.LENGTH_SHORT).show();
|
|
return;
|
|
}
|
|
startTimer();
|
|
} else if (currentFocusState == FocusState.RUNNING) {
|
|
pauseTimer();
|
|
} else if (currentFocusState == FocusState.PAUSED) {
|
|
startTimer();
|
|
}
|
|
}
|
|
|
|
private void handleSecondaryFocusClick() {
|
|
if (currentFocusState == FocusState.RUNNING) {
|
|
showFinishEarlyWarning();
|
|
} else if (currentFocusState == FocusState.PAUSED) {
|
|
cancelTimer();
|
|
}
|
|
}
|
|
|
|
private void updateFocusUI(FocusState state) {
|
|
if (!isAdded()) return;
|
|
currentFocusState = state;
|
|
|
|
if (selectedTaskForFocus == null) {
|
|
tvFocusTitle.setText("Seleciona uma tarefa");
|
|
tvFocusStatus.setText("Foca no teu objetivo");
|
|
} else {
|
|
tvFocusTitle.setText(selectedTaskForFocus.title);
|
|
tvFocusStatus.setText("Sessão de foco");
|
|
}
|
|
|
|
switch (state) {
|
|
case NOT_STARTED:
|
|
tvFocusStatus.setTextColor(ContextCompat.getColor(getContext(), R.color.text_secondary));
|
|
btnStartFocus.setText("Começar Foco");
|
|
btnSecondaryFocus.setVisibility(View.GONE);
|
|
break;
|
|
case RUNNING:
|
|
tvFocusStatus.setText("• EM FOCO");
|
|
tvFocusStatus.setTextColor(ContextCompat.getColor(getContext(), R.color.primary_purple));
|
|
btnStartFocus.setText("Pausar");
|
|
btnSecondaryFocus.setText("Concluir");
|
|
btnSecondaryFocus.setVisibility(View.VISIBLE);
|
|
break;
|
|
case PAUSED:
|
|
tvFocusStatus.setText("• PAUSADO");
|
|
tvFocusStatus.setTextColor(android.graphics.Color.parseColor("#FFA000"));
|
|
btnStartFocus.setText("Continuar");
|
|
btnSecondaryFocus.setText("Cancelar");
|
|
btnSecondaryFocus.setVisibility(View.VISIBLE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void startTimer() {
|
|
if (selectedTaskForFocus == null) return;
|
|
|
|
if (countDownTimer != null) countDownTimer.cancel();
|
|
|
|
countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
|
|
@Override
|
|
public void onTick(long millisUntilFinished) {
|
|
timeLeftInMillis = millisUntilFinished;
|
|
updateCountDownText();
|
|
}
|
|
|
|
@Override
|
|
public void onFinish() {
|
|
handleFocusComplete();
|
|
}
|
|
}.start();
|
|
|
|
isTimerRunning = true;
|
|
updateFocusUI(FocusState.RUNNING);
|
|
}
|
|
|
|
private void pauseTimer() {
|
|
if (countDownTimer != null) {
|
|
countDownTimer.cancel();
|
|
}
|
|
isTimerRunning = false;
|
|
updateFocusUI(FocusState.PAUSED);
|
|
}
|
|
|
|
private void cancelTimer() {
|
|
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
|
.setTitle("Cancelar Foco")
|
|
.setMessage("Tens a certeza que queres cancelar? Não ganharás XP.")
|
|
.setNegativeButton("Não", null)
|
|
.setPositiveButton("Sim, cancelar", (dialog, which) -> {
|
|
if (countDownTimer != null) countDownTimer.cancel();
|
|
isTimerRunning = false;
|
|
selectedTaskForFocus = null;
|
|
timeLeftInMillis = 25 * 60 * 1000;
|
|
updateCountDownText();
|
|
updateFocusUI(FocusState.NOT_STARTED);
|
|
})
|
|
.show();
|
|
}
|
|
|
|
private void showFinishEarlyWarning() {
|
|
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
|
.setTitle("Concluir cedo?")
|
|
.setMessage("Ainda não terminaste o tempo. Se concluíres agora, não ganharás o bónus de XP.")
|
|
.setNegativeButton("Continuar Foco", null)
|
|
.setPositiveButton("Concluir sem bónus", (dialog, which) -> {
|
|
// Similar to cancel but maybe we still mark task as done?
|
|
// User said "concluir → só dá XP se terminar o tempo".
|
|
// I'll just reset for now as per "XP: sessão cancelada → 0 XP"
|
|
if (countDownTimer != null) countDownTimer.cancel();
|
|
isTimerRunning = false;
|
|
selectedTaskForFocus = null;
|
|
timeLeftInMillis = 25 * 60 * 1000;
|
|
updateCountDownText();
|
|
updateFocusUI(FocusState.NOT_STARTED);
|
|
})
|
|
.show();
|
|
}
|
|
|
|
private void handleFocusComplete() {
|
|
if (isCompletingFocus) return;
|
|
isCompletingFocus = true;
|
|
|
|
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_START");
|
|
|
|
try {
|
|
if (countDownTimer != null) {
|
|
countDownTimer.cancel();
|
|
android.util.Log.d("FLUXUP_DEBUG", "TIMER_CANCELLED");
|
|
}
|
|
|
|
if (selectedTaskForFocus == null) {
|
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: selectedTask null");
|
|
isCompletingFocus = false;
|
|
return;
|
|
}
|
|
|
|
isTimerRunning = false;
|
|
updateFocusUI(FocusState.NOT_STARTED);
|
|
|
|
android.util.Log.d("FLUXUP_DEBUG", "SELECTED_TASK: " + selectedTaskForFocus.id);
|
|
|
|
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
|
if (currentUser == null) {
|
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: userId null");
|
|
isCompletingFocus = false;
|
|
return;
|
|
}
|
|
String userId = currentUser.getUid();
|
|
android.util.Log.d("FLUXUP_DEBUG", "USER_ID: " + userId);
|
|
|
|
final Task task = selectedTaskForFocus;
|
|
final String taskId = task.id;
|
|
|
|
android.util.Log.d("FLUXUP_DEBUG", "TASK_UPDATE_START");
|
|
task.completed = true;
|
|
FirestoreManager.getInstance().updateTask(task, () -> {
|
|
// Task update success is logged in FirestoreManager
|
|
|
|
android.util.Log.d("FLUXUP_DEBUG", "XP_LOG_INSERT_START");
|
|
FirestoreManager.getInstance().addXpLog(userId, 50, "focus_task", taskId);
|
|
|
|
FirestoreManager.getInstance().getUser(userId, user -> {
|
|
if (!isAdded()) {
|
|
isCompletingFocus = false;
|
|
return;
|
|
}
|
|
|
|
if (user == null) {
|
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: User object null");
|
|
isCompletingFocus = false;
|
|
return;
|
|
}
|
|
|
|
Map<String, Object> updates = new HashMap<>();
|
|
updates.put("xp", com.google.firebase.firestore.FieldValue.increment(50));
|
|
updates.put("xp_hoje", com.google.firebase.firestore.FieldValue.increment(50));
|
|
updates.put("xp_semanal", com.google.firebase.firestore.FieldValue.increment(50));
|
|
updates.put("tempo_foco_total", com.google.firebase.firestore.FieldValue.increment(task.duration));
|
|
updates.put("tempo_foco_hoje", com.google.firebase.firestore.FieldValue.increment(task.duration));
|
|
updates.put("sessoes_foco_completas", com.google.firebase.firestore.FieldValue.increment(1));
|
|
updates.put("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
|
|
updates.put("total_tasks_concluidas", com.google.firebase.firestore.FieldValue.increment(1));
|
|
|
|
int currentLevel = user.level;
|
|
int threshold = (currentLevel * (currentLevel + 1) / 2) * 100;
|
|
if (user.xp + 50 >= threshold) {
|
|
updates.put("level", currentLevel + 1);
|
|
showLevelUpAnimation(currentLevel + 1);
|
|
}
|
|
|
|
FirestoreManager.getInstance().updateUserStats(userId, updates, () -> {
|
|
android.util.Log.d("FLUXUP_DEBUG", "REFRESH_HOME_START");
|
|
refreshTodayStats();
|
|
|
|
if (isAdded()) {
|
|
android.util.Log.d("FLUXUP_DEBUG", "HOME_STATE_UPDATED");
|
|
Toast.makeText(getContext(), "Boa! Tarefa concluída +50 XP", Toast.LENGTH_LONG).show();
|
|
triggerVibration();
|
|
|
|
selectedTaskForFocus = null;
|
|
timeLeftInMillis = 25 * 60 * 1000;
|
|
updateCountDownText();
|
|
updateFocusUI(FocusState.NOT_STARTED);
|
|
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_SUCCESS");
|
|
}
|
|
isCompletingFocus = false;
|
|
});
|
|
});
|
|
});
|
|
|
|
} catch (Exception e) {
|
|
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: " + e.getMessage());
|
|
e.printStackTrace();
|
|
if (getContext() != null) {
|
|
Toast.makeText(getContext(), "Não foi possível concluir a tarefa. Tenta novamente.", Toast.LENGTH_SHORT).show();
|
|
}
|
|
isCompletingFocus = 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();
|
|
if (rankingListener != null) rankingListener.remove();
|
|
if (countDownTimer != null) countDownTimer.cancel();
|
|
}
|
|
|
|
private void showEditTaskDialog(Task task) {
|
|
View dialogView = getLayoutInflater().inflate(R.layout.dialog_add_task, null);
|
|
android.widget.EditText etTitle = dialogView.findViewById(R.id.etTaskTitle);
|
|
android.widget.EditText etDuration = dialogView.findViewById(R.id.etTaskDuration);
|
|
|
|
etTitle.setText(task.title);
|
|
etDuration.setText(String.valueOf(task.duration));
|
|
|
|
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
|
.setTitle("Editar Tarefa")
|
|
.setView(dialogView)
|
|
.setNegativeButton("Cancelar", null)
|
|
.setPositiveButton("Atualizar", (dialog, which) -> {
|
|
String title = etTitle.getText().toString().trim();
|
|
String durationStr = etDuration.getText().toString().trim();
|
|
if (!title.isEmpty()) {
|
|
task.title = title;
|
|
if (!durationStr.isEmpty()) task.duration = Integer.parseInt(durationStr);
|
|
FirestoreManager.getInstance().updateTask(task);
|
|
}
|
|
})
|
|
.show();
|
|
}
|
|
|
|
private void showAddTaskDialog() {
|
|
View dialogView = getLayoutInflater().inflate(R.layout.dialog_add_task, null);
|
|
android.widget.EditText etTitle = dialogView.findViewById(R.id.etTaskTitle);
|
|
android.widget.EditText etDuration = dialogView.findViewById(R.id.etTaskDuration);
|
|
|
|
androidx.appcompat.app.AlertDialog dialog = new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
|
.setTitle("Nova Tarefa")
|
|
.setView(dialogView)
|
|
.setNegativeButton("Cancelar", null)
|
|
.setPositiveButton("Guardar", null)
|
|
.create();
|
|
|
|
dialog.setOnShowListener(d -> {
|
|
dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE).setOnClickListener(v -> {
|
|
String title = etTitle.getText().toString().trim();
|
|
String durationStr = etDuration.getText().toString().trim();
|
|
if (title.isEmpty()) {
|
|
etTitle.setError("Obrigatório");
|
|
return;
|
|
}
|
|
int duration = 25;
|
|
if (!durationStr.isEmpty()) {
|
|
try {
|
|
duration = Integer.parseInt(durationStr);
|
|
} catch (NumberFormatException e) {
|
|
etDuration.setError("Inválido");
|
|
return;
|
|
}
|
|
}
|
|
saveNewTask(title, duration);
|
|
dialog.dismiss();
|
|
});
|
|
});
|
|
dialog.show();
|
|
}
|
|
|
|
private void saveNewTask(String title, int duration) {
|
|
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, 30, duration, uid);
|
|
FirestoreManager.getInstance().addTask(task);
|
|
}
|
|
}
|