diff --git a/app/src/main/java/com/example/citrusclient/models/Schedule.java b/app/src/main/java/com/example/citrusclient/models/Schedule.java index 27d70ca..d8b2c06 100644 --- a/app/src/main/java/com/example/citrusclient/models/Schedule.java +++ b/app/src/main/java/com/example/citrusclient/models/Schedule.java @@ -1,11 +1,9 @@ package com.example.citrusclient.models; -public class Schedule { +public class Schedule extends Task{ - private String title; private String startTime; private String endTime; - private int bookId; private int scheduleId; public Schedule(){} @@ -18,13 +16,7 @@ this.scheduleId = scheduleId; } - public String getTitle() { - return title; - } - public void setTitle(String title) { - this.title = title; - } public String getStartTime() { return startTime; @@ -42,13 +34,7 @@ this.endTime = endTime; } - public int getBookId() { - return bookId; - } - public void setBookId(int bookId) { - this.bookId = bookId; - } public int getScheduleId() { return scheduleId; diff --git a/app/src/main/java/com/example/citrusclient/models/Task.java b/app/src/main/java/com/example/citrusclient/models/Task.java new file mode 100644 index 0000000..c6e5c7f --- /dev/null +++ b/app/src/main/java/com/example/citrusclient/models/Task.java @@ -0,0 +1,23 @@ +package com.example.citrusclient.models; + +import android.content.pm.LauncherApps; + +public class Task { + int bookId; + String title; + + public int getBookId(){ + return bookId; + } + public String getTitle(){ + return title; + } + + public void setBookId(int bookId){ + this.bookId = bookId; + } + + public void setTitle(String title){ + this.title = title; + } +} diff --git a/app/src/main/java/com/example/citrusclient/models/Todo.java b/app/src/main/java/com/example/citrusclient/models/Todo.java index 8458c6b..8094845 100644 --- a/app/src/main/java/com/example/citrusclient/models/Todo.java +++ b/app/src/main/java/com/example/citrusclient/models/Todo.java @@ -2,15 +2,14 @@ import java.util.List; -public class Todo { +public class Todo extends Task{ - String title; + boolean check; int year; int month; int day; Integer todoId; - Integer bookId; //コンストラクタ public Todo(String title, boolean check, int year, int month, int day, Integer tid, Integer bid) { @@ -28,16 +27,13 @@ //セッター - public void setTitle(String title) {this.title = title;} public void setCheck(boolean check) {this.check = check;} public void setYear(int year) {this.year = year;} public void setMonth(int month) {this.month = month;} public void setDay(int day) {this.day = day;} public void setTodoId(Integer tid) {this.todoId = tid;} - public void setBookId(Integer bid) {this.bookId = bid; } //ゲッター - public String getTitle() {return title;} public boolean getCheck() {return check;} @@ -50,7 +46,6 @@ public Integer getTodoId() { return todoId; } - public Integer getBookId(){return bookId;} public boolean containsTodo(List todoList){ for(Todo todo : todoList) { diff --git a/app/src/main/java/com/example/citrusclient/rest/FavoritesRest.java b/app/src/main/java/com/example/citrusclient/rest/FavoritesRest.java index 8cf4caa..0e3dd95 100644 --- a/app/src/main/java/com/example/citrusclient/rest/FavoritesRest.java +++ b/app/src/main/java/com/example/citrusclient/rest/FavoritesRest.java @@ -1,4 +1,62 @@ package com.example.citrusclient.rest; +import java.util.HashMap; +import java.util.HashSet; + +import retrofit2.Call; +import retrofit2.http.DELETE; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.PUT; +import retrofit2.http.Path; +import retrofit2.http.Query; + public interface FavoritesRest { + //主{account_id}がいいねした本の一覧 + @FormUrlEncoded + @GET("accounts/{account_id}/favorites") + Call>> getFavoritesBooks( + @Path("account_id") String accountId, + @Query("token") String token + ); + + //主{account_id}がいいねした誰か{other_account_id}の本の一覧 + @FormUrlEncoded + @GET("accounts/{account_id}/favorites/{other_account_id}") + Call> getFavoritesBooksById( + @Path("account_id") String accountId, + @Path("other_account_id") String otherAccountId, + @Query("token") String token + ); + + //主{account_id}のある本{book_id}をいいねした人の一覧 + @FormUrlEncoded + @GET("accounts/{account_id}/books/{book_id}/favorited") + Call> getFavoritedAccount( + @Path("account_id") String accountId, + @Path("book_id") Integer bookId, + @Query("token") String token + ); + + //主{account_id}のある本{book_id}を他の人{other_account_id}がいいねする + @FormUrlEncoded + @PUT("accounts/{account_id}/books/{book_id}/favorited/{other_account_id}") + Call putFavorite( + @Path("account_id") String accountId, + @Path("book_id") Integer bookId, + @Path("other_account_id") String otherAccountId, + @Field("token") String token + ); + + //主{account_id}のある本{book_id}を他の人{other_account_id}がいいねを解除する + @FormUrlEncoded + @DELETE("accounts/{account_id}/books/{book_id}/favorited/{other_account_id}") + Call removeFavorite( + @Path("account_id") String accountId, + @Path("book_id") Integer bookId, + @Path("other_account_id") String otherAccountId, + @Query("token") String token + ); + } diff --git a/app/src/main/java/com/example/citrusclient/viewmodels/FavoritesViewModel.java b/app/src/main/java/com/example/citrusclient/viewmodels/FavoritesViewModel.java new file mode 100644 index 0000000..bd53028 --- /dev/null +++ b/app/src/main/java/com/example/citrusclient/viewmodels/FavoritesViewModel.java @@ -0,0 +1,20 @@ +package com.example.citrusclient.viewmodels; + +import com.example.citrusclient.rest.FavoritesRest; + +import androidx.lifecycle.ViewModel; +import retrofit2.Retrofit; +import retrofit2.converter.jackson.JacksonConverterFactory; + +public class FavoritesViewModel extends ViewModel { + private final Retrofit retrofit; + private final FavoritesRest favoritesRest; + + public FavoritesViewModel(){ + this.retrofit = new Retrofit.Builder() + .baseUrl("http://nitta-lab-www.is.konan-u.ac.jp/citrus/") + .addConverterFactory(JacksonConverterFactory.create()) + .build(); + this.favoritesRest = retrofit.create(FavoritesRest.class); + } +} diff --git a/app/src/main/java/com/example/citrusclient/viewmodels/ScheduleViewModel.java b/app/src/main/java/com/example/citrusclient/viewmodels/ScheduleViewModel.java index 7c49525..700826f 100644 --- a/app/src/main/java/com/example/citrusclient/viewmodels/ScheduleViewModel.java +++ b/app/src/main/java/com/example/citrusclient/viewmodels/ScheduleViewModel.java @@ -182,7 +182,8 @@ if(response.isSuccessful()){ schedulesByMonth.setValue(response.body()); } else { - errorLiveData.setValue(response.message()); + schedulesByMonth.setValue(new HashMap<>()); + errorLiveData.setValue(response.message()); } } @Override diff --git a/app/src/main/java/com/example/citrusclient/views/CalendarFragment.java b/app/src/main/java/com/example/citrusclient/views/CalendarFragment.java index 1de74fd..47a0b82 100644 --- a/app/src/main/java/com/example/citrusclient/views/CalendarFragment.java +++ b/app/src/main/java/com/example/citrusclient/views/CalendarFragment.java @@ -18,6 +18,8 @@ import android.view.ViewTreeObserver; import android.widget.Button; import android.widget.LinearLayout; +import android.widget.RadioGroup; +import android.widget.RatingBar; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; @@ -26,8 +28,11 @@ import com.example.citrusclient.R; import com.example.citrusclient.models.Book; import com.example.citrusclient.models.Schedule; +import com.example.citrusclient.models.Task; +import com.example.citrusclient.models.Todo; import com.example.citrusclient.viewmodels.BooksViewModel; import com.example.citrusclient.viewmodels.ScheduleViewModel; +import com.example.citrusclient.viewmodels.TodosViewModel; import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.time.DayOfWeek; @@ -90,6 +95,7 @@ scheduleViewModel = new ViewModelProvider(this).get(ScheduleViewModel.class); booksViewModel = new ViewModelProvider(this).get(BooksViewModel.class); + todosViewModel = new ViewModelProvider(this).get(TodosViewModel.class); schedules = new HashMap<>(); } @@ -105,13 +111,17 @@ BooksViewModel booksViewModel; private List scheduleList; ScheduleViewModel scheduleViewModel; + TodosViewModel todosViewModel; private HashMap integerBookHashMap; int year; int month; int day; + HashMap books; + HashMap> schedules; + HashMap> todos; public TextView[][] calendar(int firstDayOfWeek, int prevMonthDay, int lastDay) { int curDay = 1; @@ -170,12 +180,13 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - //AdapterはそれぞれのRecyclerViewに入れる必要があるため、for文を用いて、それぞれにセットする。(後期の作業) - Citrus citrus = (Citrus)(getActivity().getApplication()); String token = citrus.getToken(); String accountId = citrus.getAccountId(); + todos = new HashMap<>(); + schedules = new HashMap<>(); + scheduleViewModel.getSchedulesByMonth().observe(getViewLifecycleOwner(), new Observer>>() { @Override public void onChanged(HashMap> integerHashMapHashMap) { @@ -185,6 +196,45 @@ } }); + booksViewModel.getBookLiveData().observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(HashMap integerBookHashMap) { + books = integerBookHashMap; + if(books != null) { + TextView curMonth = view.findViewById(R.id.month); + if(todos != null) { + todos.clear(); + } else { + todos = new HashMap<>(); + } + + for(int bookId:books.keySet()){ + todosViewModel.loadTodosByMonth(accountId, bookId, year, month, token); + } + + updateCalendar(curMonth); + } + } + }); + + todosViewModel.getTodosByMonthLiveData().observe(getViewLifecycleOwner(), new Observer>>() { + @Override + public void onChanged(HashMap> integerHashMapHashMap) { + TextView curMonth = view.findViewById(R.id.month); + for (int day:integerHashMapHashMap.keySet()){ + if(todos.get(day) == null){ + todos.put(day, new HashMap<>()); + } + for(int todoId:integerHashMapHashMap.get(day).keySet()){ + todos.get(day).put(todoId, integerHashMapHashMap.get(day).get(todoId)); + } + } + updateCalendar(curMonth); + } + }); + + booksViewModel.loadBooks(accountId, token); + tableLayout = view.findViewById(R.id.calendarlayout); Calendar calendar = Calendar.getInstance(); @@ -231,7 +281,6 @@ year++; } scheduleViewModel.updateSchedulesByMonth(accountId, year, month, token); - } }); @@ -248,6 +297,16 @@ } }); + view.findViewById(R.id.rbTodo).setOnClickListener(view1 -> { + updateCalendar(curMonth); + }); + view.findViewById(R.id.rbSchedule).setOnClickListener(view1 -> { + updateCalendar(curMonth); + }); + view.findViewById(R.id.rbBoth).setOnClickListener(view1 -> { + updateCalendar(curMonth); + }); + //カレンダーの初期表示 TableLayout tableLayout = view.findViewById(R.id.calendarlayout); TextView[][] days = calendar(firstDayOfWeek, prevMonthDay, lastDay); @@ -257,18 +316,29 @@ for(int j = 0; j < 7; j++) { LinearLayout layout = new LinearLayout(requireContext()); layout.setOrientation(LinearLayout.VERTICAL); - layout.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.MATCH_PARENT)); + layout.setLayoutParams(new TableRow.LayoutParams(0, TableRow.LayoutParams.MATCH_PARENT)); TableRow.LayoutParams p2 = (TableRow.LayoutParams) layout.getLayoutParams(); p2.weight = 1; tableRow.addView(layout); layout.addView(days[i][j]); + final int ii = i; + final int jj = j; + layout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + citrus.setCurMonth(month); + citrus.setCurYear(year); + citrus.setCurDay(Integer.parseInt(daysString[ii][jj])); + ((MainActivity) getActivity()).showFragment(new HomeFragment()); + } + }); RecyclerView recyclerView = new RecyclerView(requireContext()); RecyclerView.LayoutManager layoutmanager = new LinearLayoutManager(requireContext()); recyclerView.setLayoutManager(layoutmanager); - List schedules = new ArrayList<>(); + List schedules = new ArrayList<>(); - recyclerView.setAdapter(new MyScheduleAdapter(schedules, integerBookHashMap)); + recyclerView.setAdapter(new MyScheduleAdapter(schedules, books)); layout.addView(recyclerView); layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override @@ -303,24 +373,53 @@ int lastDay = CurLastDay.getDayOfMonth(); String[][] days = calendarString(firstDayOfWeek, prevMonthDay, lastDay); + int one = 0; + RadioGroup selectButton = getView().findViewById(R.id.selectButton); for(int i = 0; i < 6; i++) { TableRow tableRow = (TableRow) tableLayout.getChildAt(i); for(int j = 0; j < 7; j++) { LinearLayout layout = (LinearLayout) tableRow.getChildAt(j); RecyclerView recyclerView = (RecyclerView) layout.getChildAt(1); - List schedules = new ArrayList<>(); - if(this.schedules != null) { - if (this.schedules.get(Integer.parseInt(days[i][j])) != null) { - for (Schedule schedule : this.schedules.get(Integer.parseInt(days[i][j])).values()) { - schedules.add(schedule); - } + List schedules = new ArrayList<>(); + if(days[i][j].equals("1")){ + one++; + } + if(this.schedules != null && one == 1) { + + int select = selectButton.getCheckedRadioButtonId(); + if(select != -1){ + if(select == R.id.rbTodo){ + if (this.todos.get(Integer.parseInt(days[i][j])) != null) { + for (Todo schedule : this.todos.get(Integer.parseInt(days[i][j])).values()) { + schedules.add(schedule); + } + } + } else if(select == R.id.rbSchedule){ + if (this.schedules.get(Integer.parseInt(days[i][j])) != null) { + for (Schedule schedule : this.schedules.get(Integer.parseInt(days[i][j])).values()) { + schedules.add(schedule); + } + } + } else { + if (this.todos.get(Integer.parseInt(days[i][j])) != null) { + for (Todo schedule : this.todos.get(Integer.parseInt(days[i][j])).values()) { + schedules.add(schedule); + } + } + if (this.schedules.get(Integer.parseInt(days[i][j])) != null) { + for (Schedule schedule : this.schedules.get(Integer.parseInt(days[i][j])).values()) { + schedules.add(schedule); + } + } + } + + } } - ((MyScheduleAdapter) recyclerView.getAdapter()).setSchedules(schedules, integerBookHashMap); + ((MyScheduleAdapter) recyclerView.getAdapter()).setSchedules(schedules, books); ((TextView) layout.getChildAt(0)).setText(days[i][j]); - //if(i == 2 && j == 1) Log.i("kjda", layout.getLayoutParams().height + ""); } } } @@ -328,10 +427,10 @@ class MyScheduleAdapter extends RecyclerView.Adapter { - private List scheduleList; + private List scheduleList; private HashMap integerBookHashMap; - MyScheduleAdapter(List schedules, HashMap integerBookHashMap) { + MyScheduleAdapter(List schedules, HashMap integerBookHashMap) { this.scheduleList = schedules; if(integerBookHashMap != null) { this.integerBookHashMap = new HashMap<>(integerBookHashMap); @@ -340,7 +439,7 @@ } } - public void setSchedules(List schedules, HashMap integerBookHashMap) { + public void setSchedules(List schedules, HashMap integerBookHashMap) { scheduleList = schedules; if(integerBookHashMap != null) { this.integerBookHashMap = new HashMap<>(integerBookHashMap); @@ -361,7 +460,7 @@ int red = 169; int green = 169; int blue = 169; - Schedule scheduleData = this.scheduleList.get(position); + Task scheduleData = this.scheduleList.get(position); holder.scheduleText.setText(scheduleData.getTitle()); Book book = integerBookHashMap.get(scheduleData.getBookId()); if(book != null) { diff --git a/app/src/main/java/com/example/citrusclient/views/HomeFragment.java b/app/src/main/java/com/example/citrusclient/views/HomeFragment.java index 73ddb7d..7ce0a8c 100644 --- a/app/src/main/java/com/example/citrusclient/views/HomeFragment.java +++ b/app/src/main/java/com/example/citrusclient/views/HomeFragment.java @@ -35,11 +35,17 @@ import java.security.PrivateKey; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + /** * A simple {@link Fragment} subclass. * Use the {@link HomeFragment#newInstance} factory method to @@ -299,12 +305,21 @@ } public void setTodos(List todos ,HashMap idBookHashMap) { +// Collections.sort(books, new Comparator() { +// @Override +// public int compare(Book b1, Book b2) { +// return Integer.compare(b1.getBookId(), b2.getBookId()); +// } +// }); todoList = todos; if (idBookHashMap != null) { this.idBookHashMap = new HashMap<>(idBookHashMap); } else { this.idBookHashMap = new HashMap<>(); // 空のHashMapを作成 } + + sortTodosById(); + notifyDataSetChanged(); } @@ -352,10 +367,21 @@ return todoList.size(); } - public void sortTodosById(Todo todo) { - notifyDataSetChanged(); + private void sortTodosById() { + Collections.sort(todoList, new Comparator() { + @Override + public int compare(Todo todo1, Todo todo2) { + int bookComparison = Integer.compare(todo1.getBookId(), todo2.getBookId()); + if (bookComparison != 0) { + return bookComparison; // bookIdでの比較 + } + return Integer.compare(todo1.getTodoId(), todo2.getTodoId()); // 同じbookIdの場合、todoIdで比較 + } + }); + notifyDataSetChanged(); // データ変更をアダプタに通知 } + static class MyTodoViewHolder extends RecyclerView.ViewHolder { Button todoButton; CheckBox todoCheckBox; @@ -403,6 +429,8 @@ int blue = 169; Schedule scheduleData = this.scheduleList.get(position); holder.scheduleButton.setText(scheduleData.getTitle()); +// holder.scheduleButton.setText(scheduleData.getTitle() + extractionTime(scheduleData.getStartTime()) + " ~ " + extractionTime(scheduleData.getEndTime())); + System.out.println(scheduleData.getEndTime()); Book book = idBookHashMap.get(scheduleData.getBookId()); if(book != null) { red = Integer.parseInt(book.getColor().substring(1, 3), 16); @@ -414,6 +442,46 @@ } +// private void sortScheduleByTime() { +// Collections.sort(scheduleList, new Comparator() { +// @Override +// public int compare(Schedule schedule1, Schedule schedule2) { +// return Integer.compare(schedule1.getStartTime(), schedule2.getStartTime()); +// } +// }); +// notifyDataSetChanged(); // データ変更をアダプタに通知 +// } + + private static int convertTimeInteger(String scheduleTime) { + try { + // フォーマッタを定義 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); + + // StringをLocalDateTimeに変換 + LocalDateTime dateTime = LocalDateTime.parse(scheduleTime, formatter); + + // 年、月、日、時、分を抽出 + int year = dateTime.getYear(); + int month = dateTime.getMonthValue(); + int day = dateTime.getDayOfMonth(); + int hour = dateTime.getHour(); + int minute = dateTime.getMinute(); + + // 必要に応じて整数を組み合わせる(例: YYYYMMDDHHMM) + int result = year * 1000000 + month * 10000 + day * 100 + hour * 10 + minute; + + return result; + } catch (DateTimeParseException e) { + e.printStackTrace(); + return -1; // エラーが発生した場合は-1を返す + } + } + + private static int extractionTime(String scheduleTime) { + int time = convertTimeInteger(scheduleTime); + int result = time % 10000; + return result; + } @Override public int getItemCount() { diff --git a/app/src/main/java/com/example/citrusclient/views/SettingsFragment.java b/app/src/main/java/com/example/citrusclient/views/SettingsFragment.java new file mode 100644 index 0000000..113dad8 --- /dev/null +++ b/app/src/main/java/com/example/citrusclient/views/SettingsFragment.java @@ -0,0 +1,62 @@ +package com.example.citrusclient.views; + +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.example.citrusclient.R; + +/** + * A simple {@link Fragment} subclass. Use the {@link SettingsFragment#newInstance} factory method + * to create an instance of this fragment. + */ +public class SettingsFragment extends Fragment { + + // TODO: Rename parameter arguments, choose names that match + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER + private static final String ARG_PARAM1 = "param1"; + private static final String ARG_PARAM2 = "param2"; + + // TODO: Rename and change types of parameters + private String mParam1; + private String mParam2; + + public SettingsFragment() { + // Required empty public constructor + } + + /** + * Use this factory method to create a new instance of this fragment using the provided + * parameters. + * + * @param param1 Parameter 1. + * @param param2 Parameter 2. + * @return A new instance of fragment SettingsFragment. + */ + // TODO: Rename and change types and number of parameters + public static SettingsFragment newInstance(String param1, String param2) { + SettingsFragment fragment = new SettingsFragment(); + Bundle args = new Bundle(); + args.putString(ARG_PARAM1, param1); + args.putString(ARG_PARAM2, param2); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mParam1 = getArguments().getString(ARG_PARAM1); + mParam2 = getArguments().getString(ARG_PARAM2); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_settings, container, false); + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_calendar.xml b/app/src/main/res/layout/fragment_calendar.xml index 30349d4..ac66c68 100644 --- a/app/src/main/res/layout/fragment_calendar.xml +++ b/app/src/main/res/layout/fragment_calendar.xml @@ -101,7 +101,7 @@ + android:text="todo" /> + android:text="schedule" /> + android:text="todoANDschedule" /> + + + + + + \ No newline at end of file