diff --git a/app/src/main/java/com/example/vdcscore/ui/clubs/Club.java b/app/src/main/java/com/example/vdcscore/ui/clubs/Club.java new file mode 100644 index 0000000..960778c --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/clubs/Club.java @@ -0,0 +1,41 @@ +package com.example.vdcscore.ui.clubs; + +public class Club { + private String name; + private String stadium; + private String logoUrl; + + public Club() { + // Default constructor required for calls to DataSnapshot.getValue(Club.class) + } + + public Club(String name, String stadium, String logoUrl) { + this.name = name; + this.stadium = stadium; + this.logoUrl = logoUrl; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getStadium() { + return stadium; + } + + public void setStadium(String stadium) { + this.stadium = stadium; + } + + public String getLogoUrl() { + return logoUrl; + } + + public void setLogoUrl(String logoUrl) { + this.logoUrl = logoUrl; + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/clubs/ClubAdapter.java b/app/src/main/java/com/example/vdcscore/ui/clubs/ClubAdapter.java new file mode 100644 index 0000000..dac4be3 --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/clubs/ClubAdapter.java @@ -0,0 +1,62 @@ +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.example.vdcscore.R; + +import java.util.List; + +public class ClubAdapter extends RecyclerView.Adapter { + + private final List mClubs; + + public ClubAdapter(List clubs) { + mClubs = clubs; + } + + @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); + } + + @Override + public int getItemCount() { + return mClubs.size(); + } + + static class ClubViewHolder extends RecyclerView.ViewHolder { + private final TextView name; + private final TextView stadium; + private final ImageView logo; + + public ClubViewHolder(@NonNull View itemView) { + super(itemView); + name = itemView.findViewById(R.id.text_club_name); + stadium = itemView.findViewById(R.id.text_club_stadium); + logo = itemView.findViewById(R.id.image_club_logo); + } + + public void bind(final Club club) { + name.setText(club.getName()); + stadium.setText(club.getStadium()); + // TODO: Load image from logoUrl using a library like Glide or Picasso + // For now we leave the default placeholder + } + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/clubs/ClubsFragment.java b/app/src/main/java/com/example/vdcscore/ui/clubs/ClubsFragment.java new file mode 100644 index 0000000..201af11 --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/clubs/ClubsFragment.java @@ -0,0 +1,93 @@ +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.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.vdcscore.R; +import com.example.vdcscore.databinding.FragmentClubsBinding; +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 static final String TAG = "ClubsFragment"; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + binding = FragmentClubsBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + + mDatabase = FirebaseDatabase.getInstance().getReference().child("clubs"); + + RecyclerView recyclerView = binding.recyclerClubs; + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + ProgressBar progressBar = binding.progressBar; + + progressBar.setVisibility(View.VISIBLE); + + mDatabase.addValueEventListener(new ValueEventListener() { + @Override + public void onDataChange(@NonNull DataSnapshot snapshot) { + List clubs = new ArrayList<>(); + for (DataSnapshot postSnapshot : snapshot.getChildren()) { + Club club = postSnapshot.getValue(Club.class); + clubs.add(club); + } + ClubAdapter adapter = new ClubAdapter(clubs); + recyclerView.setAdapter(adapter); + progressBar.setVisibility(View.GONE); + + if (clubs.isEmpty()) { + // Add mock data if empty for demonstration + addMockClubsIfEmpty(); + } + } + + @Override + public void onCancelled(@NonNull DatabaseError error) { + Log.w(TAG, "loadClubs:onCancelled", error.toException()); + Toast.makeText(getContext(), "Failed to load clubs.", Toast.LENGTH_SHORT).show(); + progressBar.setVisibility(View.GONE); + } + }); + + return root; + } + + private void addMockClubsIfEmpty() { + // If database is empty, optional helper to add data? + // For now, let's keep it strictly reading from Firebase or showing empty state. + // But to ensure user sees something if they haven't set up DB yet: + List mockClubs = new ArrayList<>(); + mockClubs.add(new Club("VDC", "Campo Principal", "")); + mockClubs.add(new Club("Benfica", "Estádio da Luz", "")); + ClubAdapter adapter = new ClubAdapter(mockClubs); + binding.recyclerClubs.setAdapter(adapter); + + Toast.makeText(getContext(), "No clubs found in Firebase. Showing mock data.", Toast.LENGTH_LONG).show(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/livegames/Game.java b/app/src/main/java/com/example/vdcscore/ui/livegames/Game.java new file mode 100644 index 0000000..6beae17 --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/livegames/Game.java @@ -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; + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/livegames/GameAdapter.java b/app/src/main/java/com/example/vdcscore/ui/livegames/GameAdapter.java new file mode 100644 index 0000000..17f6ec1 --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/livegames/GameAdapter.java @@ -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 { + + private final List mGames; + private final OnGameClickListener mListener; + + public interface OnGameClickListener { + void onGameClick(Game game); + } + + public GameAdapter(List 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)); + } + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/livegames/GameViewModel.java b/app/src/main/java/com/example/vdcscore/ui/livegames/GameViewModel.java new file mode 100644 index 0000000..5dd1762 --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/livegames/GameViewModel.java @@ -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> mGames; + private final MutableLiveData mSelectedGame; + + public GameViewModel() { + mGames = new MutableLiveData<>(); + mSelectedGame = new MutableLiveData<>(); + loadMockGames(); + } + + public LiveData> getGames() { + return mGames; + } + + public LiveData getSelectedGame() { + return mSelectedGame; + } + + public void selectGame(Game game) { + mSelectedGame.setValue(game); + } + + private void loadMockGames() { + List 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); + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/livegames/LiveGameDetailFragment.java b/app/src/main/java/com/example/vdcscore/ui/livegames/LiveGameDetailFragment.java new file mode 100644 index 0000000..eaa0512 --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/livegames/LiveGameDetailFragment.java @@ -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; + } +} diff --git a/app/src/main/java/com/example/vdcscore/ui/livegames/LiveGamesFragment.java b/app/src/main/java/com/example/vdcscore/ui/livegames/LiveGamesFragment.java new file mode 100644 index 0000000..cbc4109 --- /dev/null +++ b/app/src/main/java/com/example/vdcscore/ui/livegames/LiveGamesFragment.java @@ -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; + } +} diff --git a/app/src/main/res/layout/fragment_clubs.xml b/app/src/main/res/layout/fragment_clubs.xml new file mode 100644 index 0000000..17c55f0 --- /dev/null +++ b/app/src/main/res/layout/fragment_clubs.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/app/src/main/res/layout/fragment_live_game_detail.xml b/app/src/main/res/layout/fragment_live_game_detail.xml new file mode 100644 index 0000000..08c7893 --- /dev/null +++ b/app/src/main/res/layout/fragment_live_game_detail.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_live_games.xml b/app/src/main/res/layout/fragment_live_games.xml new file mode 100644 index 0000000..813018d --- /dev/null +++ b/app/src/main/res/layout/fragment_live_games.xml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/app/src/main/res/layout/item_club.xml b/app/src/main/res/layout/item_club.xml new file mode 100644 index 0000000..1c9f740 --- /dev/null +++ b/app/src/main/res/layout/item_club.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_live_game.xml b/app/src/main/res/layout/item_live_game.xml new file mode 100644 index 0000000..16f539d --- /dev/null +++ b/app/src/main/res/layout/item_live_game.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml index c2a3711..1a02cb3 100644 --- a/app/src/main/res/menu/activity_main_drawer.xml +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -12,6 +12,14 @@ android:id="@+id/nav_gallery" android:icon="@drawable/ic_menu_gallery" android:title="@string/menu_gallery" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1f0174c..fd42283 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,6 +11,8 @@ Classificação Jornadas Definições + Jogos ao Vivo + Clubes Alterar Foto de Perfil