Merge pull request 'feature/wallet' (#146) from feature/wallet into main
Reviewed-on: #146
This commit is contained in:
commit
e17d392af9
|
@ -17,6 +17,7 @@
|
|||
<option value="$PROJECT_DIR$/feature/debug" />
|
||||
<option value="$PROJECT_DIR$/feature/parent" />
|
||||
<option value="$PROJECT_DIR$/feature/setting" />
|
||||
<option value="$PROJECT_DIR$/feature/wallet" />
|
||||
<option value="$PROJECT_DIR$/model" />
|
||||
<option value="$PROJECT_DIR$/shared" />
|
||||
<option value="$PROJECT_DIR$/utils" />
|
||||
|
|
|
@ -46,6 +46,7 @@ dependencies {
|
|||
implementation project(':feature:child')
|
||||
implementation project(':feature:setting')
|
||||
implementation project(':feature:common')
|
||||
implementation project(':feature:wallet')
|
||||
|
||||
implementation project(':data')
|
||||
|
||||
|
|
|
@ -20,4 +20,9 @@
|
|||
android:id="@+id/feature_setting_navigation"
|
||||
android:icon="@drawable/settings_24px"
|
||||
android:title="Setting" />
|
||||
|
||||
<item
|
||||
android:id="@+id/feature_wallet_parent_navigation"
|
||||
android:icon="@drawable/wallet_24px"
|
||||
android:title="Wallet" />
|
||||
</menu>
|
|
@ -8,4 +8,5 @@
|
|||
<include app:graph="@navigation/feature_child_navigation" />
|
||||
<include app:graph="@navigation/feature_parent_navigation" />
|
||||
<include app:graph="@navigation/feature_setting_navigation" />
|
||||
<include app:graph="@navigation/feature_wallet_parent_navigation" />
|
||||
</navigation>
|
|
@ -5,11 +5,12 @@ import java.util.concurrent.CompletableFuture;
|
|||
|
||||
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
||||
import one.nem.kidshift.model.ChildModel;
|
||||
import one.nem.kidshift.model.HistoryModel;
|
||||
import one.nem.kidshift.model.ParentModel;
|
||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||
|
||||
/**
|
||||
* データの同期など, ユーザーからの操作に基づかない処理を行う
|
||||
* データの同期などを提供する内部ユーティリティ
|
||||
*/
|
||||
public interface KSActions {
|
||||
|
||||
|
@ -25,4 +26,9 @@ public interface KSActions {
|
|||
*/
|
||||
CompletableFuture<ParentModel> syncParent();
|
||||
|
||||
/**
|
||||
* 履歴情報同期
|
||||
*/
|
||||
CompletableFuture<List<HistoryModel>> syncHistory(String childId);
|
||||
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ public interface RewardData {
|
|||
* 現時点の合計報酬額を取得する
|
||||
* @return Integer 合計報酬額
|
||||
*/
|
||||
CompletableFuture<Integer> getTotalReward();
|
||||
CompletableFuture<Integer> getTotalReward(String childId);
|
||||
}
|
||||
|
|
|
@ -10,12 +10,15 @@ import one.nem.kidshift.data.UserSettings;
|
|||
import one.nem.kidshift.data.retrofit.KidShiftApiService;
|
||||
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.converter.ChildModelConverter;
|
||||
import one.nem.kidshift.data.retrofit.model.converter.HistoryModelConverter;
|
||||
import one.nem.kidshift.data.retrofit.model.converter.ParentModelConverter;
|
||||
import one.nem.kidshift.data.retrofit.model.converter.TaskModelConverter;
|
||||
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.HistoryListResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
||||
import one.nem.kidshift.data.room.utils.CacheWrapper;
|
||||
import one.nem.kidshift.model.ChildModel;
|
||||
import one.nem.kidshift.model.HistoryModel;
|
||||
import one.nem.kidshift.model.ParentModel;
|
||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||
import one.nem.kidshift.utils.KSLogger;
|
||||
|
@ -61,7 +64,7 @@ public class KSActionsImpl implements KSActions {
|
|||
return fetchChildListAsync().thenCombine(fetchTaskListAsync(), (childListResponse, taskListResponse) -> {
|
||||
Thread cacheThread = new Thread(() -> {
|
||||
logger.debug("キャッシュ更新スレッド開始(スレッドID: " + Thread.currentThread().getId() + ")");
|
||||
cacheWrapper.updateCache(ChildModelConverter.childListResponseToChildModelList(childListResponse),
|
||||
cacheWrapper.updateChildTaskCache(ChildModelConverter.childListResponseToChildModelList(childListResponse),
|
||||
TaskModelConverter.taskListResponseToTaskItemModelList(taskListResponse)).join();
|
||||
logger.info("キャッシュ更新完了");
|
||||
});
|
||||
|
@ -152,4 +155,31 @@ public class KSActionsImpl implements KSActions {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<HistoryModel>> syncHistory(String childId) {
|
||||
CompletableFuture<HistoryListResponse> callHistoryApi = CompletableFuture.supplyAsync(() -> {
|
||||
Call<HistoryListResponse> call = kidShiftApiService.getHistory(childId);
|
||||
try {
|
||||
Response<HistoryListResponse> response = call.execute();
|
||||
if (!response.isSuccessful()) {
|
||||
logger.error("Error fetching history list: " + response.errorBody().string());
|
||||
throw new RuntimeException("Error fetching history list: " + response.errorBody().string());
|
||||
}
|
||||
return response.body();
|
||||
} catch (Exception e) {
|
||||
logger.error("Error fetching history list");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
CompletableFuture<TaskListResponse> callTaskApi = fetchTaskListAsync();
|
||||
|
||||
return CompletableFuture.allOf(callHistoryApi, callTaskApi).thenApplyAsync(result -> {
|
||||
HistoryListResponse historyListResponse = callHistoryApi.join();
|
||||
TaskListResponse taskListResponse = callTaskApi.join();
|
||||
return HistoryModelConverter.historyListResponseAndTaskListResponseToHistoryModelList(historyListResponse, taskListResponse);
|
||||
});
|
||||
// TODO: キャッシュ更新
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
package one.nem.kidshift.data.impl;
|
||||
|
||||
import com.github.javafaker.Faker;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import one.nem.kidshift.data.RewardData;
|
||||
import one.nem.kidshift.utils.KSLogger;
|
||||
|
||||
public class RewardDataDummyImpl implements RewardData {
|
||||
|
||||
private final Faker faker;
|
||||
|
||||
@Inject
|
||||
public RewardDataDummyImpl() {
|
||||
faker = new Faker();
|
||||
// logger.setTag("RewardDataDummyImpl");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Integer> getTotalReward() {
|
||||
return CompletableFuture.supplyAsync(() -> faker.number().numberBetween(0, 1000));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package one.nem.kidshift.data.impl;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import one.nem.kidshift.data.KSActions;
|
||||
import one.nem.kidshift.data.RewardData;
|
||||
import one.nem.kidshift.data.UserSettings;
|
||||
import one.nem.kidshift.data.room.utils.CacheWrapper;
|
||||
import one.nem.kidshift.model.HistoryModel;
|
||||
import one.nem.kidshift.utils.KSLogger;
|
||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||
|
||||
public class RewardDataImpl implements RewardData {
|
||||
|
||||
private final UserSettings userSettings;
|
||||
private final KSActions ksActions;
|
||||
private final CacheWrapper cacheWrapper;
|
||||
private final KSLogger logger;
|
||||
|
||||
|
||||
@Inject
|
||||
public RewardDataImpl(KSLoggerFactory ksLoggerFactory, CacheWrapper cacheWrapper, UserSettings userSettings, KSActions ksActions) {
|
||||
this.userSettings = userSettings;
|
||||
this.ksActions = ksActions;
|
||||
this.cacheWrapper = cacheWrapper;
|
||||
this.logger = ksLoggerFactory.create("RewardDataImpl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Integer> getTotalReward(String childId) {
|
||||
return CompletableFuture.supplyAsync(() -> ksActions.syncHistory(childId).join().stream().mapToInt(HistoryModel::getReward).sum());
|
||||
}
|
||||
}
|
|
@ -5,12 +5,12 @@ import dagger.Module;
|
|||
import dagger.hilt.InstallIn;
|
||||
import dagger.hilt.android.components.FragmentComponent;
|
||||
import one.nem.kidshift.data.RewardData;
|
||||
import one.nem.kidshift.data.impl.RewardDataDummyImpl;
|
||||
import one.nem.kidshift.data.impl.RewardDataImpl;
|
||||
|
||||
@Module
|
||||
@InstallIn(FragmentComponent.class)
|
||||
abstract public class RewardDataDummyModule {
|
||||
public abstract class RewardDataModule {
|
||||
|
||||
@Binds
|
||||
public abstract RewardData bindRewardData(RewardDataDummyImpl rewardDataDummyImpl);
|
||||
}
|
||||
public abstract RewardData bindRewardData(RewardDataImpl rewardDataImpl);
|
||||
}
|
|
@ -8,6 +8,7 @@ import one.nem.kidshift.data.retrofit.model.child.ChildResponse;
|
|||
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.parent.auth.ParentAuthRequest;
|
||||
import one.nem.kidshift.data.retrofit.model.parent.auth.ParentAuthResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.HistoryListResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.TaskAddRequest;
|
||||
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.TaskResponse;
|
||||
|
@ -134,4 +135,8 @@ public interface KidShiftApiService {
|
|||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||
Call<ChildLoginCodeResponse> issueLoginCode(@Path("id") String id);
|
||||
|
||||
@GET("/task/history/{childId}")
|
||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||
Call<HistoryListResponse> getHistory(@Path("childId") String childId);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package one.nem.kidshift.data.retrofit.model.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import one.nem.kidshift.data.retrofit.model.task.HistoryListResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.HistoryResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
||||
import one.nem.kidshift.data.retrofit.model.task.TaskResponse;
|
||||
import one.nem.kidshift.model.HistoryModel;
|
||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||
|
||||
public class HistoryModelConverter { // TODO: JavaDoc
|
||||
|
||||
public static HistoryModel historyResponseToHistoryModel(HistoryResponse historyResponse) {
|
||||
HistoryModel historyModel = new HistoryModel();
|
||||
historyModel.setId(historyResponse.getId());
|
||||
historyModel.setTaskId(historyResponse.getTaskId());
|
||||
historyModel.setChildId(historyResponse.getChildId());
|
||||
historyModel.setRegisteredAt(historyResponse.getRegisteredAt());
|
||||
return historyModel;
|
||||
}
|
||||
|
||||
public static HistoryResponse historyModelToHistoryResponse(HistoryModel historyModel) {
|
||||
HistoryResponse historyResponse = new HistoryResponse();
|
||||
historyResponse.setId(historyModel.getId());
|
||||
historyResponse.setTaskId(historyModel.getTaskId());
|
||||
historyResponse.setChildId(historyModel.getChildId());
|
||||
historyResponse.setRegisteredAt(historyModel.getRegisteredAt());
|
||||
return historyResponse;
|
||||
}
|
||||
|
||||
public static List<HistoryModel> historyListResponseToHistoryModelList(HistoryListResponse historyListResponse) {
|
||||
List<HistoryModel> historyModelList = new ArrayList<>();
|
||||
for (HistoryResponse historyResponse : historyListResponse.getList()) {
|
||||
historyModelList.add(historyResponseToHistoryModel(historyResponse));
|
||||
}
|
||||
return historyModelList;
|
||||
}
|
||||
|
||||
public static HistoryListResponse historyModelListToHistoryListResponse(List<HistoryModel> historyModelList) {
|
||||
HistoryListResponse historyListResponse = new HistoryListResponse();
|
||||
List<HistoryResponse> historyResponseList = new ArrayList<>();
|
||||
for (HistoryModel historyModel : historyModelList) {
|
||||
historyResponseList.add(historyModelToHistoryResponse(historyModel));
|
||||
}
|
||||
historyListResponse.setList(historyResponseList);
|
||||
return historyListResponse;
|
||||
}
|
||||
|
||||
private static TaskResponse emptyTaskItemModel() {
|
||||
TaskResponse taskResponse = new TaskResponse();
|
||||
taskResponse.setId("");
|
||||
taskResponse.setName("Critical Error occurred(Your data (on server) is may be corrupted.)");
|
||||
taskResponse.setReward(0);
|
||||
return taskResponse;
|
||||
}
|
||||
|
||||
public static List<HistoryModel> historyListResponseAndTaskListResponseToHistoryModelList(HistoryListResponse historyListResponse, TaskListResponse taskListResponse) {
|
||||
List<HistoryModel> historyModelList = new ArrayList<>();
|
||||
for (HistoryResponse historyResponse : historyListResponse.getList()) {
|
||||
HistoryModel historyModel = historyResponseToHistoryModel(historyResponse);
|
||||
if (taskListResponse == null || taskListResponse.getList() == null || taskListResponse.getList().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
TaskItemModel taskItemModel = TaskModelConverter.taskResponseToTaskItemModel(
|
||||
Objects.requireNonNull(taskListResponse.getList().stream()
|
||||
.filter(taskResponse -> taskResponse.getId().equals(historyModel.getTaskId()))
|
||||
.findFirst().orElse(emptyTaskItemModel())));
|
||||
historyModel.setTaskName(taskItemModel.getName());
|
||||
historyModel.setReward(taskItemModel.getReward());
|
||||
historyModelList.add(historyModel);
|
||||
}
|
||||
return historyModelList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package one.nem.kidshift.data.retrofit.model.task;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class HistoryBaseItem {
|
||||
private String id;
|
||||
private String taskId;
|
||||
private String childId;
|
||||
private Date registeredAt;
|
||||
|
||||
public HistoryBaseItem(String id, String taskId, String childId, Date registeredAt) {
|
||||
this.id = id;
|
||||
this.taskId = taskId;
|
||||
this.childId = childId;
|
||||
this.registeredAt = registeredAt;
|
||||
}
|
||||
|
||||
public HistoryBaseItem() {
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void setTaskId(String taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public String getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
public void setChildId(String childId) {
|
||||
this.childId = childId;
|
||||
}
|
||||
|
||||
public Date getRegisteredAt() {
|
||||
return registeredAt;
|
||||
}
|
||||
|
||||
public void setRegisteredAt(Date registeredAt) {
|
||||
this.registeredAt = registeredAt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package one.nem.kidshift.data.retrofit.model.task;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HistoryListResponse {
|
||||
List<HistoryResponse> list;
|
||||
|
||||
public HistoryListResponse(List<HistoryResponse> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public HistoryListResponse() {
|
||||
}
|
||||
|
||||
public List<HistoryResponse> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<HistoryResponse> list) {
|
||||
this.list = list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package one.nem.kidshift.data.retrofit.model.task;
|
||||
|
||||
public class HistoryResponse extends HistoryBaseItem {
|
||||
// Additional fields
|
||||
}
|
|
@ -4,13 +4,15 @@ import androidx.room.Database;
|
|||
import androidx.room.RoomDatabase;
|
||||
|
||||
import one.nem.kidshift.data.room.dao.ChildCacheDao;
|
||||
import one.nem.kidshift.data.room.dao.HistoryCacheDao;
|
||||
import one.nem.kidshift.data.room.dao.TaskCacheDao;
|
||||
import one.nem.kidshift.data.room.dao.TaskChildLinkageDao;
|
||||
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
|
||||
import one.nem.kidshift.data.room.entity.HistoryCacheEntity;
|
||||
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
|
||||
import one.nem.kidshift.data.room.entity.TaskChildLinkageEntity;
|
||||
|
||||
@Database(entities = {ChildCacheEntity.class, TaskCacheEntity.class, TaskChildLinkageEntity.class}, version = 1)
|
||||
@Database(entities = {ChildCacheEntity.class, TaskCacheEntity.class, TaskChildLinkageEntity.class, HistoryCacheEntity.class}, version = 2)
|
||||
public abstract class KidShiftDatabase extends RoomDatabase {
|
||||
|
||||
public abstract ChildCacheDao childCacheDao();
|
||||
|
@ -19,4 +21,6 @@ public abstract class KidShiftDatabase extends RoomDatabase {
|
|||
|
||||
public abstract TaskChildLinkageDao taskChildLinkageDao();
|
||||
|
||||
public abstract HistoryCacheDao historyCacheDao();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package one.nem.kidshift.data.room.converter;
|
||||
|
||||
import androidx.room.TypeConverter;
|
||||
|
||||
public class DateTypeConverter {
|
||||
|
||||
@TypeConverter
|
||||
public static java.util.Date fromTimestamp(Long value) {
|
||||
return value == null ? null : new java.util.Date(value);
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static Long dateToTimestamp(java.util.Date date) {
|
||||
return date == null ? null : date.getTime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package one.nem.kidshift.data.room.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.OnConflictStrategy;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import one.nem.kidshift.data.room.entity.HistoryCacheEntity;
|
||||
import one.nem.kidshift.data.room.model.HistoryWithTask;
|
||||
|
||||
@Dao
|
||||
public interface HistoryCacheDao {
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
void insertHistory(HistoryCacheEntity history);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
void insertHistoryList(List<HistoryCacheEntity> historyList);
|
||||
|
||||
@Query("SELECT * FROM history_cache WHERE id = :historyId")
|
||||
HistoryCacheEntity getHistory(String historyId);
|
||||
|
||||
@Query("SELECT * FROM history_cache")
|
||||
List<HistoryCacheEntity> getHistoryList();
|
||||
|
||||
@Query("SELECT * FROM history_cache WHERE child_id = :childId")
|
||||
List<HistoryCacheEntity> getHistoryListByChildId(String childId);
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM history_cache")
|
||||
List<HistoryWithTask> getHistoryWithTasks();
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM history_cache WHERE child_id = :childId")
|
||||
List<HistoryWithTask> getHistoryWithTasksByChildId(String childId);
|
||||
|
||||
@Query("SELECT * FROM history_cache WHERE task_id = :taskId")
|
||||
List<HistoryCacheEntity> getHistoryListByTaskId(String taskId);
|
||||
|
||||
@Query("DELETE FROM history_cache WHERE id = :historyId")
|
||||
void deleteHistory(String historyId);
|
||||
|
||||
@Query("DELETE FROM history_cache WHERE child_id = :childId")
|
||||
void deleteHistoryByChildId(String childId);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package one.nem.kidshift.data.room.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
import androidx.room.TypeConverters;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import one.nem.kidshift.data.room.converter.DateTypeConverter;
|
||||
|
||||
@Entity(tableName = "history_cache")
|
||||
@TypeConverters({DateTypeConverter.class})
|
||||
public class HistoryCacheEntity {
|
||||
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "id")
|
||||
@NonNull
|
||||
public String id;
|
||||
|
||||
@ColumnInfo(name = "child_id")
|
||||
public String childId;
|
||||
|
||||
@ColumnInfo(name = "task_id")
|
||||
public String taskId;
|
||||
|
||||
@ColumnInfo(name = "registered_at")
|
||||
public Date registeredAt;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package one.nem.kidshift.data.room.model;
|
||||
|
||||
import androidx.room.Embedded;
|
||||
import androidx.room.Relation;
|
||||
|
||||
import one.nem.kidshift.data.room.entity.HistoryCacheEntity;
|
||||
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
|
||||
|
||||
public class HistoryWithTask {
|
||||
@Embedded
|
||||
public HistoryCacheEntity history;
|
||||
|
||||
@Relation(
|
||||
parentColumn = "task_id",
|
||||
entityColumn = "id"
|
||||
)
|
||||
public TaskCacheEntity task;
|
||||
}
|
|
@ -9,13 +9,17 @@ import javax.inject.Inject;
|
|||
import dagger.Module;
|
||||
import dagger.hilt.InstallIn;
|
||||
import dagger.hilt.components.SingletonComponent;
|
||||
import one.nem.kidshift.data.retrofit.model.converter.HistoryModelConverter;
|
||||
import one.nem.kidshift.data.room.KidShiftDatabase;
|
||||
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
|
||||
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
|
||||
import one.nem.kidshift.data.room.entity.TaskChildLinkageEntity;
|
||||
import one.nem.kidshift.data.room.model.HistoryWithTask;
|
||||
import one.nem.kidshift.data.room.utils.converter.ChildCacheConverter;
|
||||
import one.nem.kidshift.data.room.utils.converter.HistoryCacheConverter;
|
||||
import one.nem.kidshift.data.room.utils.converter.TaskCacheConverter;
|
||||
import one.nem.kidshift.model.ChildModel;
|
||||
import one.nem.kidshift.model.HistoryModel;
|
||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||
import one.nem.kidshift.utils.KSLogger;
|
||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||
|
@ -39,7 +43,7 @@ public class CacheWrapper {
|
|||
* @param taskList タスクリスト
|
||||
* @return CompletableFuture
|
||||
*/
|
||||
public CompletableFuture<Void> updateCache(List<ChildModel> childList, List<TaskItemModel> taskList) {
|
||||
public CompletableFuture<Void> updateChildTaskCache(List<ChildModel> childList, List<TaskItemModel> taskList) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
logger.debug("Updating cache");
|
||||
insertChildList(childList).join();
|
||||
|
@ -65,6 +69,12 @@ public class CacheWrapper {
|
|||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> updateHistoryCache(List<HistoryModel> historyList) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
kidShiftDatabase.historyCacheDao().insertHistoryList(HistoryCacheConverter.historyModelListToHistoryCacheEntityList(historyList));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 子供リストをDBに挿入する
|
||||
* @param childList 子供リスト
|
||||
|
@ -109,5 +119,12 @@ public class CacheWrapper {
|
|||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<List<HistoryModel>> getHistoryList(String childId) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
List<HistoryWithTask> result = kidShiftDatabase.historyCacheDao().getHistoryWithTasksByChildId(childId);
|
||||
return HistoryCacheConverter.historyWithTaskListToHistoryModelList(result);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package one.nem.kidshift.data.room.utils.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import one.nem.kidshift.data.room.entity.HistoryCacheEntity;
|
||||
import one.nem.kidshift.data.room.model.HistoryWithTask;
|
||||
import one.nem.kidshift.model.HistoryModel;
|
||||
|
||||
public class HistoryCacheConverter {
|
||||
|
||||
public static HistoryCacheEntity historyModelToHistoryCacheEntity(HistoryModel historyModel) {
|
||||
HistoryCacheEntity historyCacheEntity = new HistoryCacheEntity();
|
||||
historyCacheEntity.id = historyModel.getId();
|
||||
historyCacheEntity.taskId = historyModel.getTaskId();
|
||||
historyCacheEntity.childId = historyModel.getChildId();
|
||||
historyCacheEntity.registeredAt = historyModel.getRegisteredAt();
|
||||
return historyCacheEntity;
|
||||
}
|
||||
|
||||
public static HistoryModel historyCacheEntityToHistoryModel(HistoryCacheEntity historyCacheEntity) {
|
||||
HistoryModel historyModel = new HistoryModel();
|
||||
historyModel.setId(historyCacheEntity.id);
|
||||
historyModel.setTaskId(historyCacheEntity.taskId);
|
||||
historyModel.setChildId(historyCacheEntity.childId);
|
||||
historyModel.setRegisteredAt(historyCacheEntity.registeredAt);
|
||||
return historyModel;
|
||||
}
|
||||
|
||||
public static List<HistoryCacheEntity> historyModelListToHistoryCacheEntityList(List<HistoryModel> historyModelList) {
|
||||
List<HistoryCacheEntity> historyCacheEntityList = new ArrayList<>();
|
||||
for (HistoryModel historyModel : historyModelList) {
|
||||
historyCacheEntityList.add(historyModelToHistoryCacheEntity(historyModel));
|
||||
}
|
||||
return historyCacheEntityList;
|
||||
}
|
||||
|
||||
public static List<HistoryModel> historyCacheEntityListToHistoryModelList(List<HistoryCacheEntity> historyCacheEntityList) {
|
||||
List<HistoryModel> historyModelList = new ArrayList<>();
|
||||
for (HistoryCacheEntity historyCacheEntity : historyCacheEntityList) {
|
||||
historyModelList.add(historyCacheEntityToHistoryModel(historyCacheEntity));
|
||||
}
|
||||
return historyModelList;
|
||||
}
|
||||
|
||||
public static List<HistoryModel> historyWithTaskListToHistoryModelList(List<HistoryWithTask> result) {
|
||||
List<HistoryModel> historyModelList = new ArrayList<>();
|
||||
for (HistoryWithTask historyWithTask : result) {
|
||||
HistoryModel historyModel = new HistoryModel();
|
||||
historyModel.setId(historyWithTask.history.id);
|
||||
historyModel.setTaskId(historyWithTask.history.taskId);
|
||||
historyModel.setChildId(historyWithTask.history.childId);
|
||||
historyModel.setRegisteredAt(historyWithTask.history.registeredAt);
|
||||
historyModel.setTaskName(historyWithTask.task.name);
|
||||
historyModel.setReward(historyWithTask.task.reward);
|
||||
historyModelList.add(historyModel);
|
||||
}
|
||||
return historyModelList;
|
||||
}
|
||||
}
|
|
@ -90,24 +90,24 @@ public class ChildMainFragment extends Fragment {
|
|||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
|
||||
logger.addTag("ChildMainFragment");
|
||||
|
||||
Integer reward = rewardData.getTotalReward().join();
|
||||
|
||||
logger.debug("取得したデータ: " + reward);
|
||||
|
||||
Calendar cl = Calendar.getInstance();
|
||||
TextView tr = view.findViewById(R.id.totalReward);
|
||||
TextView dv = view.findViewById(R.id.dateView);
|
||||
Date date = new Date();
|
||||
|
||||
|
||||
NumberFormat nf = NumberFormat.getNumberInstance();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat();
|
||||
sdf.applyPattern("yyyy年MM月");
|
||||
|
||||
dv.setText(sdf.format(cl.getTime()) + " お小遣い総額");
|
||||
tr.setText("¥" + nf.format(reward).toString());
|
||||
//
|
||||
// logger.addTag("ChildMainFragment");
|
||||
//
|
||||
// Integer reward = rewardData.getTotalReward().join();
|
||||
//
|
||||
// logger.debug("取得したデータ: " + reward);
|
||||
//
|
||||
// Calendar cl = Calendar.getInstance();
|
||||
// TextView tr = view.findViewById(R.id.totalReward);
|
||||
// TextView dv = view.findViewById(R.id.dateView);
|
||||
// Date date = new Date();
|
||||
//
|
||||
//
|
||||
// NumberFormat nf = NumberFormat.getNumberInstance();
|
||||
// SimpleDateFormat sdf = new SimpleDateFormat();
|
||||
// sdf.applyPattern("yyyy年MM月");
|
||||
//
|
||||
// dv.setText(sdf.format(cl.getTime()) + " お小遣い総額");
|
||||
// tr.setText("¥" + nf.format(reward).toString());
|
||||
}
|
||||
}
|
1
feature/wallet/.gitignore
vendored
Normal file
1
feature/wallet/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
49
feature/wallet/build.gradle
Normal file
49
feature/wallet/build.gradle
Normal file
|
@ -0,0 +1,49 @@
|
|||
plugins {
|
||||
alias(libs.plugins.androidLibrary)
|
||||
id 'com.google.dagger.hilt.android'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'one.nem.kidshift.wallet'
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
minSdk 28
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation libs.appcompat
|
||||
implementation libs.material
|
||||
implementation libs.navigation.fragment
|
||||
implementation libs.navigation.ui
|
||||
testImplementation libs.junit
|
||||
androidTestImplementation libs.ext.junit
|
||||
androidTestImplementation libs.espresso.core
|
||||
implementation libs.androidx.swiperefreshlayout
|
||||
|
||||
// Hilt (DI)
|
||||
implementation libs.com.google.dagger.hilt.android
|
||||
annotationProcessor libs.com.google.dagger.hilt.compiler
|
||||
|
||||
// Project modules
|
||||
implementation project(':model')
|
||||
implementation project(':utils')
|
||||
implementation project(':data')
|
||||
implementation project(':shared')
|
||||
}
|
0
feature/wallet/consumer-rules.pro
Normal file
0
feature/wallet/consumer-rules.pro
Normal file
21
feature/wallet/proguard-rules.pro
vendored
Normal file
21
feature/wallet/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,26 @@
|
|||
package one.nem.kidshift.wallet;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("one.nem.kidshift.wallet.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
4
feature/wallet/src/main/AndroidManifest.xml
Normal file
4
feature/wallet/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,90 @@
|
|||
package one.nem.kidshift.wallet;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import dagger.hilt.android.AndroidEntryPoint;
|
||||
import one.nem.kidshift.data.KSActions;
|
||||
import one.nem.kidshift.data.RewardData;
|
||||
import one.nem.kidshift.utils.FabManager;
|
||||
import one.nem.kidshift.utils.KSLogger;
|
||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||
|
||||
@AndroidEntryPoint
|
||||
public class WalletContentFragment extends Fragment {
|
||||
|
||||
private static final String ARG_CHILD_ID = "childId";
|
||||
|
||||
@Inject
|
||||
KSLoggerFactory loggerFactory;
|
||||
@Inject
|
||||
RewardData rewardData;
|
||||
|
||||
@Inject
|
||||
FabManager fabManager;
|
||||
|
||||
private KSLogger logger;
|
||||
private String childId;
|
||||
|
||||
private TextView totalRewardTextView;
|
||||
|
||||
public WalletContentFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
public static WalletContentFragment newInstance(String childId) {
|
||||
WalletContentFragment fragment = new WalletContentFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_CHILD_ID, childId);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
childId = getArguments().getString(ARG_CHILD_ID);
|
||||
}
|
||||
logger = loggerFactory.create("WalletMainFragment");
|
||||
logger.debug("Received parameter: " + childId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_wallet_content, container, false);
|
||||
|
||||
totalRewardTextView = view.findViewById(R.id.totalRewardTextView);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
}
|
||||
|
||||
private void updateTotalReward() {
|
||||
rewardData.getTotalReward(childId).thenAccept(totalReward -> {
|
||||
logger.debug("Total reward: " + totalReward);
|
||||
totalRewardTextView.setText(String.valueOf(totalReward) + "円");
|
||||
}).exceptionally(throwable -> {
|
||||
logger.error("Failed to get total reward: " + throwable.getMessage());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateTotalReward();
|
||||
fabManager.hide();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package one.nem.kidshift.wallet;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.hilt.android.AndroidEntryPoint;
|
||||
import one.nem.kidshift.data.ChildData;
|
||||
import one.nem.kidshift.data.RewardData;
|
||||
import one.nem.kidshift.model.ChildModel;
|
||||
import one.nem.kidshift.utils.KSLogger;
|
||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||
|
||||
@AndroidEntryPoint
|
||||
public class WalletParentWrapperFragment extends Fragment {
|
||||
|
||||
@Inject
|
||||
KSLoggerFactory loggerFactory;
|
||||
|
||||
private KSLogger logger;
|
||||
|
||||
@Inject
|
||||
ChildData childData;
|
||||
|
||||
@Inject
|
||||
RewardData rewardData;
|
||||
|
||||
private TabLayout tabLayout;
|
||||
private ViewPager2 viewPager;
|
||||
|
||||
public WalletParentWrapperFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_wallet_parent_wrapper, container, false);
|
||||
|
||||
tabLayout = view.findViewById(R.id.tabLayout);
|
||||
viewPager = view.findViewById(R.id.viewPager);
|
||||
|
||||
TabAdapter tabAdapter = new TabAdapter(requireActivity());
|
||||
|
||||
// デバッグ用
|
||||
List<ChildModel> childList = childData.getChildListDirect().join();
|
||||
tabAdapter.setChildList(childList);
|
||||
|
||||
viewPager.setAdapter(tabAdapter);
|
||||
|
||||
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
|
||||
tab.setText(childList.get(position).getName());
|
||||
}).attach();
|
||||
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private static class TabAdapter extends FragmentStateAdapter {
|
||||
|
||||
private List<ChildModel> childList;
|
||||
|
||||
public void setChildList(List<ChildModel> childList) {
|
||||
this.childList = childList;
|
||||
}
|
||||
|
||||
public TabAdapter(@NonNull FragmentActivity fragmentActivity) {
|
||||
super(fragmentActivity);
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
return WalletContentFragment.newInstance(childList.get(position).getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return childList == null ? 0 : childList.size();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".WalletContentFragment"
|
||||
android:id="@+id/swipeRefreshLayout">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/frameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/historyItemRecyclerView"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="24dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="今月の支払い総額"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/totalRewardTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="0000円"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Display2" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/historyItemRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".WalletParentWrapperFragment">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tabLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/feature_wallet_child_navigation"
|
||||
app:startDestination="@id/walletMainFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/walletMainFragment"
|
||||
android:name="one.nem.kidshift.wallet.WalletContentFragment"
|
||||
android:label="fragment_wallet_main"
|
||||
tools:layout="@layout/fragment_wallet_content" />
|
||||
</navigation>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/feature_wallet_parent_navigation"
|
||||
app:startDestination="@id/walletParentWrapperFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/walletParentWrapperFragment"
|
||||
android:name="one.nem.kidshift.wallet.WalletParentWrapperFragment"
|
||||
android:label="fragment_wallet_parent_wrapper"
|
||||
tools:layout="@layout/fragment_wallet_parent_wrapper" />
|
||||
</navigation>
|
4
feature/wallet/src/main/res/values/strings.xml
Normal file
4
feature/wallet/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<resources>
|
||||
<!-- TODO: Remove or change this placeholder text -->
|
||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||
</resources>
|
|
@ -0,0 +1,17 @@
|
|||
package one.nem.kidshift.wallet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
79
model/src/main/java/one/nem/kidshift/model/HistoryModel.java
Normal file
79
model/src/main/java/one/nem/kidshift/model/HistoryModel.java
Normal file
|
@ -0,0 +1,79 @@
|
|||
package one.nem.kidshift.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class HistoryModel {
|
||||
private String id;
|
||||
private String taskId;
|
||||
private String taskName;
|
||||
private String childId;
|
||||
private Date registeredAt;
|
||||
private int reward;
|
||||
|
||||
public HistoryModel(String id, String taskId, String taskName, String childId, Date registeredAt, int reward) {
|
||||
this.id = id;
|
||||
this.taskId = taskId;
|
||||
this.taskName = taskName;
|
||||
this.childId = childId;
|
||||
this.registeredAt = registeredAt;
|
||||
this.reward = reward;
|
||||
}
|
||||
|
||||
public HistoryModel(String id, String taskId, String childId, Date registeredAt) { // 他モデルとのマージが必要なので
|
||||
this.id = id;
|
||||
this.taskId = taskId;
|
||||
this.childId = childId;
|
||||
this.registeredAt = registeredAt;
|
||||
}
|
||||
|
||||
public HistoryModel() {
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void setTaskId(String taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public String getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
public void setChildId(String childId) {
|
||||
this.childId = childId;
|
||||
}
|
||||
|
||||
public Date getRegisteredAt() {
|
||||
return registeredAt;
|
||||
}
|
||||
|
||||
public void setRegisteredAt(Date registeredAt) {
|
||||
this.registeredAt = registeredAt;
|
||||
}
|
||||
|
||||
public int getReward() {
|
||||
return reward;
|
||||
}
|
||||
|
||||
public void setReward(int reward) {
|
||||
this.reward = reward;
|
||||
}
|
||||
}
|
|
@ -34,3 +34,4 @@ include ':data'
|
|||
include ':model'
|
||||
include ':shared'
|
||||
include ':feature:common'
|
||||
include ':feature:wallet'
|
||||
|
|
10
shared/src/main/res/drawable/favorite_24px.xml
Normal file
10
shared/src/main/res/drawable/favorite_24px.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M479.62,788.38Q466.77,788.38 453.81,783.77Q440.85,779.15 431,769.31L373.54,717.08Q267.16,620.08 183.58,526.5Q100,432.92 100,326Q100,240.85 157.42,183.42Q214.85,126 300,126Q348.38,126 395.58,148.31Q442.77,170.62 480,220.77Q517.23,170.62 564.42,148.31Q611.62,126 660,126Q745.15,126 802.58,183.42Q860,240.85 860,326Q860,434.08 775,528.73Q690,623.38 585.46,717.69L528.61,769.31Q518.77,779.15 505.62,783.77Q492.46,788.38 479.62,788.38ZM451.23,281.54Q418.77,232.08 382.88,209.04Q347,186 300,186Q240,186 200,226Q160,266 160,326Q160,374.15 191.04,426.69Q222.08,479.23 268.96,531.15Q315.84,583.08 370.54,632.61Q425.23,682.15 471.92,724.69Q475.38,727.77 480,727.77Q484.62,727.77 488.08,724.69Q534.77,682.15 589.46,632.61Q644.16,583.08 691.04,531.15Q737.92,479.23 768.96,426.69Q800,374.15 800,326Q800,266 760,226Q720,186 660,186Q613,186 577.12,209.04Q541.23,232.08 508.77,281.54Q503.69,289.23 496,293.08Q488.31,296.92 480,296.92Q471.69,296.92 464,293.08Q456.31,289.23 451.23,281.54ZM480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Q480,457.46 480,457.46Z"/>
|
||||
</vector>
|
10
shared/src/main/res/drawable/wallet_24px.xml
Normal file
10
shared/src/main/res/drawable/wallet_24px.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,780Q182.08,780 141.04,738.96Q100,697.92 100,640L100,320Q100,262.08 141.04,221.04Q182.08,180 240,180L720,180Q777.92,180 818.96,221.04Q860,262.08 860,320L860,640Q860,697.92 818.96,738.96Q777.92,780 720,780L240,780ZM240,330L720,330Q742.77,330 762.96,336.54Q783.15,343.08 800,356.39L800,320Q800,287 776.5,263.5Q753,240 720,240L240,240Q207,240 183.5,263.5Q160,287 160,320L160,356.39Q176.85,343.08 197.04,336.54Q217.23,330 240,330ZM163.69,449.62L612.92,558.77Q621.15,560.77 629.58,558.96Q638,557.15 644.85,551.54L788.85,430.54Q779,412.46 760.65,401.23Q742.31,390 720,390L240,390Q211.69,390 190.85,406.58Q170,423.15 163.69,449.62Z"/>
|
||||
</vector>
|
Loading…
Reference in New Issue
Block a user