Compare commits
392 Commits
feature/au
...
main
Author | SHA1 | Date | |
---|---|---|---|
4dab0f33f0 | |||
d055c5fa14 | |||
e712a84564 | |||
81dfdc1fe2 | |||
ad0ad3685b | |||
f192876b4c | |||
764beff222 | |||
21df151e65 | |||
b3bb61e43b | |||
8da7b26d72 | |||
aece6909ad | |||
bba2751704 | |||
7794d664ba | |||
bef4d02dae | |||
3000fe9989 | |||
ecafb0c13a | |||
c9e1706374 | |||
bad3b72c91 | |||
53614cf033 | |||
2d9c1a10c9 | |||
fbfb02ad09 | |||
6213acc2b0 | |||
7d01ebc018 | |||
3d222cafe0 | |||
c6ee2dc75e | |||
6a4ad4de05 | |||
942e7b561b | |||
03337612a7 | |||
0421d84bd6 | |||
fc7e709cf6 | |||
1ae8335a4a | |||
cbf7f843b2 | |||
870b8be7f6 | |||
f932b935b9 | |||
ede51b124f | |||
4ba2677a15 | |||
f2c4e43b98 | |||
8129b83e16 | |||
62d298ebfd | |||
4916c05b08 | |||
161d9d7602 | |||
a4986cffbc | |||
f4b116cd27 | |||
86093a1e13 | |||
7ecd46fb98 | |||
7f8c9d74fa | |||
98cacfd561 | |||
9a8d9ef631 | |||
dc83d541e2 | |||
3a6fc8cdd7 | |||
73e2c0f1d9 | |||
696486623e | |||
70db920060 | |||
7ea5e143d6 | |||
8ea083cdf4 | |||
9173db1f88 | |||
8f77c73439 | |||
20a24b4ea3 | |||
fc0091b24a | |||
06c392af2e | |||
e2a75ba6d7 | |||
fb3b15450d | |||
36ed1a0ab9 | |||
7c2496c373 | |||
8095095ce8 | |||
6496e218af | |||
9f1a9b64a9 | |||
dc21fee2cd | |||
3959cbba5f | |||
69689e7247 | |||
f73bfeeb03 | |||
a6612c5ea9 | |||
43d00c90c3 | |||
5d5804a1f6 | |||
b08b1f54e4 | |||
aa9b997117 | |||
805cb93d59 | |||
49e8acbe2f | |||
3da941e0ae | |||
c79f9e5469 | |||
a0cf1f3ab3 | |||
21ec30ef19 | |||
05e8d15a20 | |||
d33a454ecc | |||
aace66143f | |||
e90fd8a759 | |||
9b0b710c73 | |||
16f2ed9c20 | |||
7039271e45 | |||
81ebc36c98 | |||
a37dbc9445 | |||
4293b477f5 | |||
a5dcde0d54 | |||
6160eba7ac | |||
48949d3c60 | |||
d9cb4ecfb2 | |||
00ccb3a5f0 | |||
eb2e2e5b6d | |||
94f47982f7 | |||
cc5560745f | |||
358116811f | |||
73bcefa99f | |||
c846659e4b | |||
10374d2486 | |||
2963ffec7e | |||
e714b26921 | |||
57b22b8ec4 | |||
555e0d3862 | |||
c183d43643 | |||
793ff62b41 | |||
bb2298598d | |||
00febce148 | |||
a033a3888e | |||
6769397484 | |||
c43ec08318 | |||
10ebcae612 | |||
38e9277e9b | |||
b9fed3ab71 | |||
e01a28b1c4 | |||
97ff8da8d8 | |||
39f4316345 | |||
42a972855d | |||
15426d358c | |||
c01f3012dd | |||
4d2f177a88 | |||
364f580fbc | |||
97e6bc072e | |||
8495e8021e | |||
f052710cd8 | |||
4fa39cb49b | |||
f82fcf090f | |||
434e52bf4a | |||
c8c3215c3f | |||
34e5085b63 | |||
4974bfced6 | |||
fbf49bbe43 | |||
dd32a82b7b | |||
f1c181a755 | |||
0993e46d48 | |||
5b01c048f9 | |||
a63deb01ac | |||
6fe88d9ebf | |||
160be606ae | |||
23993285af | |||
47134fcde6 | |||
dcec3c2e9e | |||
6fad20c34a | |||
bdcd30c6f8 | |||
e6c8a85c95 | |||
61eead89c6 | |||
e70bfb17cd | |||
dde0edfad7 | |||
1b1e57fb49 | |||
07c7f1c6fb | |||
cc13bdd37f | |||
8761e5ef81 | |||
04fd81a547 | |||
7142a5d30f | |||
a4d838c781 | |||
dc9b0a080f | |||
91b07b4aae | |||
cfdc160cad | |||
43cd603fcc | |||
9b8fa59f9a | |||
5f029a3a4f | |||
34497196d5 | |||
43a20fe409 | |||
e4c36e6971 | |||
9efe6e12d4 | |||
bb64622cc3 | |||
6c7f00249a | |||
c0f371a892 | |||
731c2b8033 | |||
94807508ee | |||
c1244accca | |||
4b163f6202 | |||
075bae4d2d | |||
9f930438ff | |||
0df125ba2f | |||
e252f557d0 | |||
9f07171543 | |||
722a66e1f0 | |||
fa1bdfce4b | |||
6969e841b9 | |||
70f530a8d3 | |||
1960a83185 | |||
a18a9eaf1c | |||
e8f4a5d66c | |||
ab8d309328 | |||
b025fc3abb | |||
24c40d05e3 | |||
f0182b25c2 | |||
6433a0d09a | |||
b416e93ab3 | |||
b433c8e7ed | |||
dfc159fec0 | |||
6e49695551 | |||
3d6914fa36 | |||
22f6f48bb1 | |||
833b3613e8 | |||
96b1a5ea6d | |||
b29a98ee3e | |||
c312e2ce29 | |||
4307283d40 | |||
e3d97b96c5 | |||
8bf4ed9c21 | |||
9ce71dbd64 | |||
4d23b91c2d | |||
9426988a2e | |||
9fcd0ba1aa | |||
c1d125b4f0 | |||
354fac1659 | |||
01220b933c | |||
19e99ad4f4 | |||
08945533db | |||
3c3f19c727 | |||
4cc80f9857 | |||
70d12bbc59 | |||
41a3fa3b54 | |||
da98941ed4 | |||
e98cbefcad | |||
85b8067f20 | |||
0a3eb19f6e | |||
db09196303 | |||
e25177a65b | |||
254214253f | |||
a0cb825336 | |||
c91406bd3f | |||
a9587b3917 | |||
94f10f7ce2 | |||
7c4a93a4e7 | |||
520b4701c9 | |||
e04d29b0bb | |||
dac26806c3 | |||
8a874a027f | |||
8406ac6e36 | |||
6d3e53ec72 | |||
cb15ec6568 | |||
53e9b9c588 | |||
f4cb5f5b3c | |||
3b8b7cd12c | |||
f96189e3dc | |||
58bbde92f5 | |||
ed0c30de60 | |||
7e4f6815bb | |||
70293ee51f | |||
ed877771b2 | |||
6b6d03d540 | |||
40465d526a | |||
196ce53e03 | |||
18b64d255c | |||
a3e7191c3a | |||
d7b5f4e14c | |||
7a364607bb | |||
45321ebdc3 | |||
1ba551ccb5 | |||
3fbbc7311f | |||
a9e6d16540 | |||
640d094e34 | |||
61c46b12f6 | |||
c3dec40ac0 | |||
89ce3b718f | |||
17cdf4a384 | |||
59051ee517 | |||
081b469f24 | |||
483e638754 | |||
81d708ebe3 | |||
2e9a6c5660 | |||
5dd9072f6a | |||
13b6922c6d | |||
7b85eb41af | |||
649e63d668 | |||
3e48fb8795 | |||
9d134ab0cb | |||
cc6dcb84b9 | |||
f0674c1a88 | |||
627fe279a5 | |||
d4a07d1b15 | |||
016218d673 | |||
a7a3f0f3b1 | |||
099b6a04d8 | |||
c8b70ef635 | |||
1b40da9eb0 | |||
ef510dcea2 | |||
9fbec35d20 | |||
0561f7a623 | |||
26dc837eb8 | |||
aec917a9cb | |||
0aa152ac43 | |||
e296c445fe | |||
31cdd0e9a8 | |||
1c534adca4 | |||
3650ca9b4d | |||
c1e4f75769 | |||
ef64d58c8e | |||
86c7a87f05 | |||
46dc7644cc | |||
1366e671ae | |||
5d5cb999f2 | |||
ae75a04e9d | |||
118361aff4 | |||
15a02fe501 | |||
3d173b437e | |||
3d0ea8525f | |||
c5b2e9a186 | |||
c97575ee0f | |||
f22c87011a | |||
5cb26ddc12 | |||
d6ec8f16dc | |||
94efb7ddb1 | |||
1e6a206524 | |||
553cf0db30 | |||
4d05b9e568 | |||
a531b0c5c6 | |||
93442fed23 | |||
ffb60342fd | |||
b7fa1efe3c | |||
56fd31b025 | |||
cfcf11e557 | |||
a8d1180aab | |||
208088e9b2 | |||
d207f2e4d3 | |||
cdca79818a | |||
5bc5930d5b | |||
4c1a342b58 | |||
deec9301df | |||
7e7c221ae1 | |||
e17d392af9 | |||
2ac14316b6 | |||
6be673d9a0 | |||
c6831df910 | |||
7b1e4dc698 | |||
efec0512d2 | |||
ac29832038 | |||
0579a1b45a | |||
d2c5e7e8b3 | |||
aaae868114 | |||
f1e5b0b43c | |||
a39872647b | |||
d9c1bf126b | |||
09b4d4eb33 | |||
9e987f1994 | |||
f924e498c2 | |||
e00eb0b598 | |||
e24e3d40a1 | |||
df244ae6c7 | |||
f8d03adb54 | |||
3f5160b9ce | |||
3b52cb53d7 | |||
4089c2ad86 | |||
4a03cfa6ec | |||
612ad9eb1b | |||
67fa07a9e0 | |||
1db94bc3b6 | |||
446ba17cca | |||
4d3b7ac6d2 | |||
9d449aa575 | |||
02cd9b7aab | |||
e09091f2fb | |||
0b49ee9b09 | |||
0465f54aca | |||
477152e40e | |||
f78b17dfb5 | |||
1cb47048e7 | |||
51fe42ec05 | |||
d4af873190 | |||
c5a39836cc | |||
3288b27cf0 | |||
5c6ea6c9cf | |||
67b7d3280a | |||
ffaf8dd444 | |||
1824cfd7ce | |||
369e65aecb | |||
24c3078637 | |||
f7bf16cd19 | |||
c2297dee90 | |||
5b726c5923 | |||
f0349d0e1e | |||
29e367e79d | |||
d213541bc1 | |||
9ec4818d19 | |||
9ae72b6d8e | |||
ce49d93265 | |||
db2a00e37b | |||
5973114924 | |||
298a7e4874 | |||
8a29ec64cb | |||
f3115ae951 | |||
f63268406e | |||
470852b1ec | |||
edfc33b653 | |||
02634ca94f |
|
@ -17,6 +17,7 @@
|
||||||
<option value="$PROJECT_DIR$/feature/debug" />
|
<option value="$PROJECT_DIR$/feature/debug" />
|
||||||
<option value="$PROJECT_DIR$/feature/parent" />
|
<option value="$PROJECT_DIR$/feature/parent" />
|
||||||
<option value="$PROJECT_DIR$/feature/setting" />
|
<option value="$PROJECT_DIR$/feature/setting" />
|
||||||
|
<option value="$PROJECT_DIR$/feature/wallet" />
|
||||||
<option value="$PROJECT_DIR$/model" />
|
<option value="$PROJECT_DIR$/model" />
|
||||||
<option value="$PROJECT_DIR$/shared" />
|
<option value="$PROJECT_DIR$/shared" />
|
||||||
<option value="$PROJECT_DIR$/utils" />
|
<option value="$PROJECT_DIR$/utils" />
|
||||||
|
|
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 グループワークチーム「シフトメイト」メンバー
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
36
README.md
|
@ -1,8 +1,38 @@
|
||||||
# WIP
|
# WIP
|
||||||
|
|
||||||
## メモ
|
~~## メモ
|
||||||
- リリース前(=提出前)には`DEBUG_ONLY`で検索してチェック(念のため)
|
- リリース前(=提出前)には`DEBUG_ONLY`で検索してチェック(念のため)
|
||||||
|
|
||||||
## リリース前チェック
|
## リリース前チェック
|
||||||
- DBの破壊的マイグレーションを許可するオプションを無効に
|
- DBの破壊的マイグレーションを許可するオプションを無効に~~
|
||||||
-
|
|
||||||
|
#### 補足
|
||||||
|
- カレンダーはCompactCalendarViewをそのまま使用する予定でしたが,AndroidX環境で使用するとクラス重複でビルドできないため,AndroidXに対応させるPRを取り込んだ物を専用Mavenリポジトリとして公開して使用しています
|
||||||
|
- https://github.com/r-ca/CompactCalendarView
|
||||||
|
|
||||||
|
## 補足
|
||||||
|
- 直前に大規模リファクタリングを始めていたため,未使用コード(ファイル)がいくつか残っています
|
||||||
|
- `:feature:setting`, `:feature:parent` は廃止されており, 現在は使用されていません
|
||||||
|
- `:feature:child` は子供管理画面のアクティビティのみ使用されています
|
||||||
|
|
||||||
|
- 親, 子供のタスク一覧画面はどちらも`:feature:common`の`CommonHomeFragment`を用いており, ナビゲーショングラフを切り替えることで表示モードを切り替えています
|
||||||
|
|
||||||
|
## 既知の問題
|
||||||
|
- 初回起動時, ウォレットの表示に失敗する場合がある
|
||||||
|
- 特定の操作を行った場合にナビゲーションが正常に動作しなくなる場合がある
|
||||||
|
- 特定の状況で子供モード時に追加ウィンドウが開けてしまう場合がある(APIの権限チェックではじかれるため, 実際に追加することは不可能)
|
||||||
|
- カレンダーの表示を切り替える際, RecyclerViewのアニメーションが一定範囲にしか反映されない
|
||||||
|
- お手伝い履歴がローカルキャッシュされておらず,毎回サーバーから全データを取得している
|
||||||
|
- ウォレット画面でPull-to-Refreshが動作しない
|
||||||
|
- ウォレット画面にて非UIスレッドでUI更新を行ってしまっている?
|
||||||
|
- オフライン時,ウォレットなど一部の画面でクラッシュする場合がある
|
||||||
|
- 資格情報が間違ったままログインできてしまう
|
||||||
|
- キャッシュとサーバーのマスターデータに差異があった場合, 再表示しないと表示に適応されない場合がある(コールバックの処理が適切に実装されていない画面がある)
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- 全体的なUX改善
|
||||||
|
- インメモリデータベースの活用(Related: 全体的なUX改善)
|
||||||
|
- ViewModelの本格導入
|
||||||
|
- タスクのアサイン機能への対応
|
||||||
|
- 親モードで子供画面を表示したとき, 親モードへの移動にロックをかけられるようにする
|
||||||
|
- 非DynamicColor機種で使用されるテーマの適用が中途半端なので完全に適用するように
|
|
@ -46,6 +46,7 @@ dependencies {
|
||||||
implementation project(':feature:child')
|
implementation project(':feature:child')
|
||||||
implementation project(':feature:setting')
|
implementation project(':feature:setting')
|
||||||
implementation project(':feature:common')
|
implementation project(':feature:common')
|
||||||
|
implementation project(':feature:wallet')
|
||||||
|
|
||||||
implementation project(':data')
|
implementation project(':data')
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.KidShift"
|
android:theme="@style/Theme.KidShift"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
|
<activity
|
||||||
|
android:name=".ChildLoginActivity"
|
||||||
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".RegisterActivity"
|
android:name=".RegisterActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
154
app/src/main/java/one/nem/kidshift/ChildLoginActivity.java
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
package one.nem.kidshift;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
import one.nem.kidshift.data.ChildData;
|
||||||
|
import one.nem.kidshift.data.UserSettings;
|
||||||
|
import one.nem.kidshift.data.retrofit.KidShiftApiService;
|
||||||
|
import one.nem.kidshift.data.retrofit.model.child.auth.ChildAuthRequest;
|
||||||
|
import one.nem.kidshift.data.retrofit.model.child.auth.ChildAuthResponse;
|
||||||
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
import retrofit2.Call;
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
public class ChildLoginActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
UserSettings userSettings;
|
||||||
|
@Inject
|
||||||
|
KSLoggerFactory loggerFactory;
|
||||||
|
@Inject
|
||||||
|
KidShiftApiService kidShiftApiService;
|
||||||
|
|
||||||
|
private KSLogger logger;
|
||||||
|
|
||||||
|
|
||||||
|
private EditText loginCode1, loginCode2, loginCode3, loginCode4, loginCode5, loginCode6, loginCode7, loginCode8;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
setContentView(R.layout.activity_child_login);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
|
logger = loggerFactory.create("ChildLoginActivity");
|
||||||
|
|
||||||
|
// コードのフォーカスを自動で移動する
|
||||||
|
loginCode1 = findViewById(R.id.loginCode_1);
|
||||||
|
loginCode2 = findViewById(R.id.loginCode_2);
|
||||||
|
loginCode3 = findViewById(R.id.loginCode_3);
|
||||||
|
loginCode4 = findViewById(R.id.loginCode_4);
|
||||||
|
loginCode5 = findViewById(R.id.loginCode_5);
|
||||||
|
loginCode6 = findViewById(R.id.loginCode_6);
|
||||||
|
loginCode7 = findViewById(R.id.loginCode_7);
|
||||||
|
loginCode8 = findViewById(R.id.loginCode_8);
|
||||||
|
|
||||||
|
loginCode1.addTextChangedListener(new LoginCodeTextWatcher(loginCode1, loginCode2, null));
|
||||||
|
loginCode2.addTextChangedListener(new LoginCodeTextWatcher(loginCode2, loginCode3, loginCode1));
|
||||||
|
loginCode3.addTextChangedListener(new LoginCodeTextWatcher(loginCode3, loginCode4, loginCode2));
|
||||||
|
loginCode4.addTextChangedListener(new LoginCodeTextWatcher(loginCode4, loginCode5, loginCode3));
|
||||||
|
loginCode5.addTextChangedListener(new LoginCodeTextWatcher(loginCode5, loginCode6, loginCode4));
|
||||||
|
loginCode6.addTextChangedListener(new LoginCodeTextWatcher(loginCode6, loginCode7, loginCode5));
|
||||||
|
loginCode7.addTextChangedListener(new LoginCodeTextWatcher(loginCode7, loginCode8, loginCode6));
|
||||||
|
loginCode8.addTextChangedListener(new LoginCodeTextWatcher(loginCode8, null, loginCode7));
|
||||||
|
|
||||||
|
// ログインボタンを押したときの処理
|
||||||
|
findViewById(R.id.childLoginButton).setOnClickListener(v -> {
|
||||||
|
logger.debug("ログインボタンが押されました");
|
||||||
|
Call<ChildAuthResponse> call = kidShiftApiService.childLogin(new ChildAuthRequest(getLoginCode()));
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
try {
|
||||||
|
ChildAuthResponse childAuthResponse = call.execute().body();
|
||||||
|
if (childAuthResponse == null || childAuthResponse.getAccessToken() == null) {
|
||||||
|
// エラー処理
|
||||||
|
logger.error("ChildAuthResponseがnullまたはAccessTokenがnullです");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UserSettings.AppCommonSetting appCommonSetting = userSettings.getAppCommonSetting();
|
||||||
|
appCommonSetting.setLoggedIn(true);
|
||||||
|
appCommonSetting.setAccessToken(childAuthResponse.getAccessToken());
|
||||||
|
appCommonSetting.setChildId(childAuthResponse.getChildId());
|
||||||
|
appCommonSetting.setChildMode(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("リクエストに失敗しました");
|
||||||
|
Toast.makeText(this, "ログインに失敗しました", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}).thenRun(() -> {
|
||||||
|
startActivity(new Intent(this, MainActivity.class));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLoginCode() {
|
||||||
|
return loginCode1.getText().toString() +
|
||||||
|
loginCode2.getText().toString() +
|
||||||
|
loginCode3.getText().toString() +
|
||||||
|
loginCode4.getText().toString() +
|
||||||
|
loginCode5.getText().toString() +
|
||||||
|
loginCode6.getText().toString() +
|
||||||
|
loginCode7.getText().toString() +
|
||||||
|
loginCode8.getText().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class LoginCodeTextWatcher implements TextWatcher, View.OnKeyListener {
|
||||||
|
private EditText currentView;
|
||||||
|
private final EditText nextView;
|
||||||
|
private final EditText previousView;
|
||||||
|
|
||||||
|
LoginCodeTextWatcher(EditText currentView, EditText nextView, EditText previousView) {
|
||||||
|
this.currentView = currentView;
|
||||||
|
this.nextView = nextView;
|
||||||
|
this.previousView = previousView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
if (s.length() == 1 && nextView != null) {
|
||||||
|
nextView.requestFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||||
|
// if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) { // TODO: バックスペースの処理
|
||||||
|
// EditText currentView = (EditText) v;
|
||||||
|
// if (currentView.getText().length() == 0 && previousView != null) {
|
||||||
|
// previousView.requestFocus();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,10 +54,10 @@ public class LoginActivity extends AppCompatActivity {
|
||||||
|
|
||||||
logger = loggerFactory.create("LoginActivity");
|
logger = loggerFactory.create("LoginActivity");
|
||||||
|
|
||||||
EditText emailEditText = findViewById(R.id.emailEditText);
|
EditText emailEditText = findViewById(R.id.parentLoginEmailEditText);
|
||||||
EditText passwordEditText = findViewById(R.id.passwordEditText);
|
EditText passwordEditText = findViewById(R.id.parentLoginPasswordEditText);
|
||||||
|
|
||||||
findViewById(R.id.loginButton).setOnClickListener(v -> {
|
findViewById(R.id.parentLoginButton).setOnClickListener(v -> {
|
||||||
String email = emailEditText.getText().toString(); // TODO: メールアドレスのバリデーション
|
String email = emailEditText.getText().toString(); // TODO: メールアドレスのバリデーション
|
||||||
String password = passwordEditText.getText().toString();
|
String password = passwordEditText.getText().toString();
|
||||||
|
|
||||||
|
@ -87,8 +87,12 @@ public class LoginActivity extends AppCompatActivity {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
findViewById(R.id.intentRegisterButton).setOnClickListener(v -> {
|
findViewById(R.id.toRegisterButton).setOnClickListener(v -> {
|
||||||
startActivity(new Intent(this, RegisterActivity.class));
|
startActivity(new Intent(this, RegisterActivity.class));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
findViewById(R.id.toChildLoginButton).setOnClickListener(v -> {
|
||||||
|
startActivity(new Intent(this, ChildLoginActivity.class));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,17 @@
|
||||||
package one.nem.kidshift;
|
package one.nem.kidshift;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
@ -14,35 +22,54 @@ import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.navigation.NavController;
|
import androidx.navigation.NavController;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.navigation.ui.AppBarConfiguration;
|
|
||||||
import androidx.navigation.ui.NavigationUI;
|
import androidx.navigation.ui.NavigationUI;
|
||||||
|
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.android.material.chip.Chip;
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
import com.google.android.material.divider.MaterialDivider;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
|
import com.google.android.material.navigation.NavigationView;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
import one.nem.kidshift.data.ChildData;
|
||||||
|
import one.nem.kidshift.data.ParentData;
|
||||||
import one.nem.kidshift.data.UserSettings;
|
import one.nem.kidshift.data.UserSettings;
|
||||||
|
import one.nem.kidshift.feature.child.ChildManageMainActivity;
|
||||||
|
import one.nem.kidshift.model.ParentModel;
|
||||||
|
import one.nem.kidshift.model.callback.ParentModelCallback;
|
||||||
import one.nem.kidshift.utils.FabManager;
|
import one.nem.kidshift.utils.FabManager;
|
||||||
|
import one.nem.kidshift.utils.FeatureFlag;
|
||||||
import one.nem.kidshift.utils.KSLogger;
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.ToolBarManager;
|
||||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
KSLoggerFactory loggerFactory;
|
KSLoggerFactory ksLoggerFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FabManager fabManager;
|
FabManager fabManager;
|
||||||
|
@Inject
|
||||||
private KSLogger logger;
|
ToolBarManager toolBarManager;
|
||||||
|
@Inject
|
||||||
private FloatingActionButton fab;
|
FeatureFlag featureFlag;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UserSettings userSettings;
|
UserSettings userSettings;
|
||||||
|
@Inject
|
||||||
|
ParentData parentData;
|
||||||
|
@Inject
|
||||||
|
ChildData childData;
|
||||||
|
|
||||||
|
|
||||||
|
private KSLogger logger;
|
||||||
|
private FloatingActionButton fab;
|
||||||
|
private Toolbar toolbar;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -55,11 +82,46 @@ public class MainActivity extends AppCompatActivity {
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
logger = ksLoggerFactory.create("MainActivity");
|
||||||
|
|
||||||
|
// Check logged in
|
||||||
|
if (userSettings.getAppCommonSetting().isLoggedIn()) {
|
||||||
|
logger.info("User is logged in!");
|
||||||
|
} else {
|
||||||
|
logger.info("User is not logged in!");
|
||||||
|
|
||||||
|
Intent intent = new Intent(this, LoginActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
toolBarManager.setToolbar(toolbar);
|
||||||
|
|
||||||
DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);
|
DrawerLayout drawerLayout = findViewById(R.id.drawerLayout);
|
||||||
drawerLayout.open();
|
|
||||||
|
// アイテムが選択されたときの処理
|
||||||
|
NavigationView navigationView = findViewById(R.id.navigationView);
|
||||||
|
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||||
|
logger.debug("Item selected: " + item.getItemId());
|
||||||
|
if (item.getItemId() == R.id.manage_child_account) {
|
||||||
|
Intent intent = new Intent(MainActivity.this, ChildManageMainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == R.id.show_debug_dialog) {
|
||||||
|
showDebugDialog();
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == R.id.show_account_dialog) {
|
||||||
|
showAccountDialog();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
logger.warn("不明なアイテム: " + item.getItemId());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ActionBarDrawerToggle actionBarDrawerToggle =
|
ActionBarDrawerToggle actionBarDrawerToggle =
|
||||||
new ActionBarDrawerToggle(
|
new ActionBarDrawerToggle(
|
||||||
|
@ -67,10 +129,6 @@ public class MainActivity extends AppCompatActivity {
|
||||||
drawerLayout.addDrawerListener(actionBarDrawerToggle);
|
drawerLayout.addDrawerListener(actionBarDrawerToggle);
|
||||||
actionBarDrawerToggle.syncState();
|
actionBarDrawerToggle.syncState();
|
||||||
|
|
||||||
logger = loggerFactory.create("MainActivity");
|
|
||||||
|
|
||||||
logger.info("MainActivity started!");
|
|
||||||
|
|
||||||
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_nav);
|
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_nav);
|
||||||
|
|
||||||
// Init navigation
|
// Init navigation
|
||||||
|
@ -85,14 +143,23 @@ public class MainActivity extends AppCompatActivity {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check logged in
|
UserSettings.AppCommonSetting appCommonSetting = userSettings.getAppCommonSetting();
|
||||||
if (userSettings.getAppCommonSetting().isLoggedIn()) {
|
if (appCommonSetting.isChildMode()) {
|
||||||
logger.info("User is logged in!");
|
logger.info("Child mode is enabled!");
|
||||||
} else {
|
// 保護者向けのナビゲーションを削除
|
||||||
logger.info("User is not logged in!");
|
bottomNavigationView.getMenu().removeItem(R.id.feature_common_parent_child_navigation);
|
||||||
|
bottomNavigationView.getMenu().removeItem(R.id.feature_common_parent_parent_navigation);
|
||||||
|
|
||||||
Intent intent = new Intent(this, LoginActivity.class);
|
bottomNavigationView.getMenu().removeItem(R.id.feature_wallet_parent_navigation);
|
||||||
startActivity(intent);
|
// startDestinationを変更
|
||||||
|
bottomNavigationView.setSelectedItemId(R.id.feature_common_child_child_navigation);
|
||||||
|
|
||||||
|
// manage_child_accountを削除
|
||||||
|
navigationView.getMenu().removeItem(R.id.manage_child_account);
|
||||||
|
} else {
|
||||||
|
logger.info("Child mode is disabled!");
|
||||||
|
bottomNavigationView.getMenu().removeItem(R.id.feature_common_child_child_navigation);
|
||||||
|
bottomNavigationView.getMenu().removeItem(R.id.feature_wallet_child_navigation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fab = findViewById(R.id.mainFab);
|
fab = findViewById(R.id.mainFab);
|
||||||
|
@ -105,4 +172,122 @@ public class MainActivity extends AppCompatActivity {
|
||||||
private void startup() {
|
private void startup() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showAccountDialog() {
|
||||||
|
boolean isEditMode = false;
|
||||||
|
View view = getLayoutInflater().inflate(R.layout.user_info_dialog_layout, null);
|
||||||
|
if (userSettings.getAppCommonSetting().isChildMode()) {
|
||||||
|
childData.getChild(userSettings.getAppCommonSetting().getChildId()).thenAccept(childModel -> {
|
||||||
|
((TextView) view.findViewById(R.id.userNameTextView)).setText(childModel.getName());
|
||||||
|
logger.debug("ChildModel: " + childModel.getName());
|
||||||
|
((TextView) view.findViewById(R.id.emailTextView)).setText("子供ユーザーはメールアドレスを設定できません");
|
||||||
|
((Chip) view.findViewById(R.id.chip)).setText("子供/Child");
|
||||||
|
}).join();
|
||||||
|
} else {
|
||||||
|
parentData.getParentDirect().thenAccept(parentModel -> {
|
||||||
|
((TextView) view.findViewById(R.id.userNameTextView)).setText(parentModel.getName());
|
||||||
|
logger.debug("ParentModel: " + parentModel.getName() + ", " + parentModel.getEmail());
|
||||||
|
((TextView) view.findViewById(R.id.emailTextView)).setText(parentModel.getEmail());
|
||||||
|
((Chip) view.findViewById(R.id.chip)).setText("保護者/Parent");
|
||||||
|
}).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround
|
||||||
|
if (userSettings.getAppCommonSetting().isChildMode()) {
|
||||||
|
view.findViewById(R.id.userNameEditButton).setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
view.findViewById(R.id.userNameEditButton).setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
view.findViewById(R.id.userNameEditButton).setOnClickListener(v -> {
|
||||||
|
EditText editText = new EditText(this);
|
||||||
|
editText.setText(((TextView) view.findViewById(R.id.userNameTextView)).getText());
|
||||||
|
editText.setHint("ユーザー名");
|
||||||
|
new MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle("ユーザー名の変更")
|
||||||
|
.setView(editText)
|
||||||
|
.setPositiveButton("OK", (dialog, which) -> {
|
||||||
|
((TextView) view.findViewById(R.id.userNameTextView)).setText(editText.getText());
|
||||||
|
if (userSettings.getAppCommonSetting().isChildMode()) {
|
||||||
|
// 子供モード
|
||||||
|
childData.getChild(userSettings.getAppCommonSetting().getChildId()).thenAccept(childModel -> {
|
||||||
|
childModel.setName(editText.getText().toString());
|
||||||
|
childData.updateChild(childModel);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 保護者モード
|
||||||
|
parentData.getParentDirect().thenAccept(parentModel -> {
|
||||||
|
parentModel.setName(editText.getText().toString());
|
||||||
|
parentData.updateParent(parentModel);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("キャンセル", (dialog, which) -> {
|
||||||
|
// Do nothing
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
new MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle("アカウント情報")
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton("OK", (dialog, which) -> {
|
||||||
|
// Do nothing
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDebugDialog() {
|
||||||
|
|
||||||
|
ScrollView scrollView = new ScrollView(this);
|
||||||
|
scrollView.setPadding(32, 16, 32, 16);
|
||||||
|
LinearLayout linearLayout = new LinearLayout(this);
|
||||||
|
|
||||||
|
TextView serverAddressTextView = new TextView(this);
|
||||||
|
serverAddressTextView.setText("サーバーアドレス: " + userSettings.getApiSetting().getApiBaseUrl());
|
||||||
|
serverAddressTextView.setTextSize(16);
|
||||||
|
|
||||||
|
TextView accessTokenTextView = new TextView(this);
|
||||||
|
accessTokenTextView.setText("アクセストークン: " + userSettings.getAppCommonSetting().getAccessToken());
|
||||||
|
accessTokenTextView.setTextSize(16);
|
||||||
|
|
||||||
|
TextView childModeTextView = new TextView(this);
|
||||||
|
childModeTextView.setText("子供モード: " + userSettings.getAppCommonSetting().isChildMode());
|
||||||
|
childModeTextView.setTextSize(16);
|
||||||
|
|
||||||
|
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
linearLayout.addView(serverAddressTextView);
|
||||||
|
linearLayout.addView(createDivider(this));
|
||||||
|
linearLayout.addView(accessTokenTextView);
|
||||||
|
linearLayout.addView(createDivider(this));
|
||||||
|
linearLayout.addView(childModeTextView);
|
||||||
|
|
||||||
|
scrollView.addView(linearLayout);
|
||||||
|
|
||||||
|
new MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle("参考情報(評価用)")
|
||||||
|
.setView(scrollView)
|
||||||
|
.setPositiveButton("OK", (dialog, which) -> {
|
||||||
|
// Do nothing
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private MaterialDivider createDivider(Context context) {
|
||||||
|
MaterialDivider divider = new MaterialDivider(context);
|
||||||
|
// Margin (48, 16, 48, 16)
|
||||||
|
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
);
|
||||||
|
params.setMargins(48, 16, 48, 16);
|
||||||
|
divider.setLayoutParams(params);
|
||||||
|
return divider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Toolbar getToolbar() { // TODO: toolbarのインスタンス自体を取得するのではなく,fabのように操作できるようにする
|
||||||
|
return toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -53,10 +53,10 @@ public class RegisterActivity extends AppCompatActivity {
|
||||||
|
|
||||||
logger = loggerFactory.create("RegisterActivity");
|
logger = loggerFactory.create("RegisterActivity");
|
||||||
|
|
||||||
EditText emailEditText = findViewById(R.id.emailEditText); // TODO: メールアドレスのバリデーション
|
EditText emailEditText = findViewById(R.id.parentRegisterEmailEditText); // TODO: メールアドレスのバリデーション
|
||||||
EditText passwordEditText = findViewById(R.id.passwordEditText);
|
EditText passwordEditText = findViewById(R.id.parentRegisterPasswordEditText);
|
||||||
|
|
||||||
findViewById(R.id.registerButton).setOnClickListener(v -> {
|
findViewById(R.id.parentRegisterButton).setOnClickListener(v -> {
|
||||||
String email = emailEditText.getText().toString();
|
String email = emailEditText.getText().toString();
|
||||||
String password = passwordEditText.getText().toString();
|
String password = passwordEditText.getText().toString();
|
||||||
|
|
||||||
|
@ -86,8 +86,12 @@ public class RegisterActivity extends AppCompatActivity {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
findViewById(R.id.intentLoginButton).setOnClickListener(v -> {
|
findViewById(R.id.toLoginButton).setOnClickListener(v -> {
|
||||||
startActivity(new Intent(this, LoginActivity.class));
|
startActivity(new Intent(this, LoginActivity.class));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
findViewById(R.id.toChildLoginButton).setOnClickListener(v -> {
|
||||||
|
startActivity(new Intent(this, ChildLoginActivity.class));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,30 +1,15 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="24"
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
android:tint="#333333">
|
||||||
<aapt:attr name="android:fillColor">
|
<group android:scaleX="0.435"
|
||||||
<gradient
|
android:scaleY="0.435"
|
||||||
android:endX="85.84757"
|
android:translateX="6.78"
|
||||||
android:endY="92.4963"
|
android:translateY="6.78">
|
||||||
android:startX="42.9492"
|
|
||||||
android:startY="49.59793"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFF"
|
android:fillColor="@android:color/white"
|
||||||
android:fillType="nonZero"
|
android:pathData="M22,8c0,-0.55 -0.45,-1 -1,-1h-7c-0.55,0 -1,0.45 -1,1s0.45,1 1,1h7C21.55,9 22,8.55 22,8zM13,16c0,0.55 0.45,1 1,1h7c0.55,0 1,-0.45 1,-1c0,-0.55 -0.45,-1 -1,-1h-7C13.45,15 13,15.45 13,16zM10.47,4.63c0.39,0.39 0.39,1.02 0,1.41l-4.23,4.25c-0.39,0.39 -1.02,0.39 -1.42,0L2.7,8.16c-0.39,-0.39 -0.39,-1.02 0,-1.41c0.39,-0.39 1.02,-0.39 1.41,0l1.42,1.42l3.54,-3.54C9.45,4.25 10.09,4.25 10.47,4.63zM10.48,12.64c0.39,0.39 0.39,1.02 0,1.41l-4.23,4.25c-0.39,0.39 -1.02,0.39 -1.42,0L2.7,16.16c-0.39,-0.39 -0.39,-1.02 0,-1.41s1.02,-0.39 1.41,0l1.42,1.42l3.54,-3.54C9.45,12.25 10.09,12.25 10.48,12.64L10.48,12.64z"/>
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
</group>
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
</vector>
|
160
app/src/main/res/layout/activity_child_login.xml
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
<?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:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ChildLoginActivity">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/titleTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:text="KidShiftにログイン"
|
||||||
|
android:textSize="32dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/inputContainer"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/inputContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="128dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:weightSum="10"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/titleTextView">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_1"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_2"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_3"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_4"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="-"
|
||||||
|
android:textSize="34sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_5"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_6"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_7"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/loginCode_8"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="number"
|
||||||
|
android:maxWidth="48dp"
|
||||||
|
android:maxLength="1"
|
||||||
|
android:textSize="24sp"
|
||||||
|
tools:ignore="Autofill,LabelFor" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/childLoginButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="128dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="ログイン"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/inputContainer" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -7,43 +7,85 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".LoginActivity">
|
tools:context=".LoginActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/inputContainer"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
app:layout_constraintBottom_toTopOf="@+id/linearLayout3"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/emailEditText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ems="10"
|
|
||||||
android:inputType="textEmailAddress" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/passwordEditText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ems="10"
|
|
||||||
android:inputType="textPassword" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView"
|
android:id="@+id/titleTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:text="※Loginボタン長押しでBypass"
|
android:layout_marginBottom="128dp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/linearLayout2"
|
android:text="KidShiftにログイン"
|
||||||
|
android:textSize="32dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/inputContainer"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/linearLayout2"
|
android:id="@+id/inputContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_marginBottom="128dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:weightSum="10"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/parentLoginButton"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:hint="メールアドレス">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/parentLoginEmailEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textEmailAddress" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:hint="パスワード"
|
||||||
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/parentLoginPasswordEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textPassword" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/parentLoginButton"
|
||||||
|
style="@style/Widget.Material3.Button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="128dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:paddingHorizontal="48dp"
|
||||||
|
android:text="ログイン"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/inputContainer" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout3"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
@ -52,19 +94,29 @@
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/loginButton"
|
android:id="@+id/toRegisterButton"
|
||||||
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="LOGIN" />
|
android:padding="0dp"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingTop="0dp"
|
||||||
|
android:text="新規登録" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/intentRegisterButton"
|
android:id="@+id/toChildLoginButton"
|
||||||
style="@style/Widget.Material3.Button.IconButton.Outlined"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="Register" />
|
android:padding="0dp"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingTop="0dp"
|
||||||
|
android:text="子供ログイン" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -20,13 +20,14 @@
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorSurface"
|
||||||
android:minHeight="?attr/actionBarSize"
|
android:minHeight="?attr/actionBarSize"
|
||||||
android:theme="?attr/actionBarTheme"
|
android:theme="?attr/actionBarTheme"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:title="@string/app_name" />
|
app:title="@string/app_name"
|
||||||
|
android:elevation="8dp" />
|
||||||
|
|
||||||
<androidx.fragment.app.FragmentContainerView
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/fragmentContainerView"
|
android:id="@+id/fragmentContainerView"
|
||||||
|
|
|
@ -7,43 +7,85 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".RegisterActivity">
|
tools:context=".RegisterActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/inputContainer"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
app:layout_constraintBottom_toTopOf="@+id/linearLayout3"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/emailEditText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ems="10"
|
|
||||||
android:inputType="textEmailAddress" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/passwordEditText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ems="10"
|
|
||||||
android:inputType="textPassword" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView"
|
android:id="@+id/titleTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:text="※Registerボタン長押しでBypass"
|
android:layout_marginBottom="128dp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/linearLayout2"
|
android:text="KidShiftに新規登録"
|
||||||
|
android:textSize="32dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/inputContainer"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/linearLayout2"
|
android:id="@+id/inputContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_marginBottom="128dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:weightSum="10"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/parentRegisterButton"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:hint="メールアドレス">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/parentRegisterEmailEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textEmailAddress" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:hint="パスワード"
|
||||||
|
app:passwordToggleEnabled="true">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/parentRegisterPasswordEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textPassword" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/parentRegisterButton"
|
||||||
|
style="@style/Widget.Material3.Button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="128dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:paddingHorizontal="48dp"
|
||||||
|
android:text="新規登録"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/inputContainer" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout3"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
@ -52,19 +94,29 @@
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/registerButton"
|
android:id="@+id/toLoginButton"
|
||||||
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="REGISTER" />
|
android:padding="0dp"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingTop="0dp"
|
||||||
|
android:text="ログイン" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/intentLoginButton"
|
android:id="@+id/toChildLoginButton"
|
||||||
style="@style/Widget.Material3.Button.IconButton.Outlined"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="Login" />
|
android:padding="0dp"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingTop="0dp"
|
||||||
|
android:text="子供ログイン" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -2,19 +2,15 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/colorSecondary"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp"
|
android:padding="16dp">
|
||||||
android:background="?attr/colorPrimaryDark">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/ic_launcher_foreground" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Header Title"
|
android:layout_marginTop="48dp"
|
||||||
|
android:text="KidShift"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="20sp" />
|
android:textSize="34sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
52
app/src/main/res/layout/user_info_dialog_layout.xml
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_margin="32dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/userNameTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="UNAME_PHOLDER"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/userNameEditButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:padding="24px"
|
||||||
|
app:srcCompat="@drawable/edit_24px" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/emailTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="huga@example.com" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chip"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="保護者" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,23 +1,31 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<!-- TODO: アイコン再検討 -->
|
<!-- TODO: アイコン再検討 -->
|
||||||
|
<!-- 保護者モード / 保護者目線 -->
|
||||||
<item
|
<item
|
||||||
android:id="@+id/feature_parent_navigation"
|
android:id="@+id/feature_common_parent_parent_navigation"
|
||||||
android:icon="@drawable/pending_24px"
|
android:icon="@drawable/home_24px"
|
||||||
android:title="Parent" />
|
android:title="ホーム" />
|
||||||
|
|
||||||
|
<!-- 保護者モード / 子供目線 -->
|
||||||
<item
|
<item
|
||||||
android:id="@+id/feature_child_navigation"
|
android:id="@+id/feature_common_parent_child_navigation"
|
||||||
android:icon="@drawable/child_care_24px"
|
android:icon="@drawable/child_care_24px"
|
||||||
android:title="Child" />
|
android:title="こども" />
|
||||||
|
|
||||||
|
<!-- 子供モード / 子供目線 -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/feature_common_child_child_navigation"
|
||||||
|
android:icon="@drawable/home_24px"
|
||||||
|
android:title="ホーム" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/feature_debug_navigation"
|
android:id="@+id/feature_wallet_parent_navigation"
|
||||||
android:icon="@drawable/developer_mode_24px"
|
android:icon="@drawable/wallet_24px"
|
||||||
android:title="Debug" />
|
android:title="ウォレット" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/feature_setting_navigation"
|
android:id="@+id/feature_wallet_child_navigation"
|
||||||
android:icon="@drawable/settings_24px"
|
android:icon="@drawable/wallet_24px"
|
||||||
android:title="Setting" />
|
android:title="ウォレット" />
|
||||||
</menu>
|
</menu>
|
|
@ -1,9 +1,23 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_home"
|
android:id="@+id/show_account_dialog"
|
||||||
android:title="Home" />
|
android:icon="@drawable/account_box_24px"
|
||||||
|
android:title="ユーザー情報" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_settings"
|
android:id="@+id/manage_child_account"
|
||||||
android:title="Settings" />
|
android:icon="@drawable/manage_accounts_24px"
|
||||||
|
android:title="子供アカウントの管理" />
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:title=""
|
||||||
|
android:enabled="false" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/show_debug_dialog"
|
||||||
|
android:icon="@drawable/developer_mode_24px"
|
||||||
|
android:title="デバッグ情報" />
|
||||||
</menu>
|
</menu>
|
||||||
|
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 936 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 716 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 6.8 KiB |
|
@ -2,10 +2,13 @@
|
||||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/main_nav"
|
android:id="@+id/main_nav"
|
||||||
app:startDestination="@id/feature_debug_navigation">
|
app:startDestination="@id/feature_common_parent_parent_navigation">
|
||||||
|
|
||||||
<include app:graph="@navigation/feature_debug_navigation" />
|
<include app:graph="@navigation/feature_debug_navigation" />
|
||||||
<include app:graph="@navigation/feature_child_navigation" />
|
<include app:graph="@navigation/feature_child_navigation" />
|
||||||
<include app:graph="@navigation/feature_parent_navigation" />
|
<include app:graph="@navigation/feature_common_parent_parent_navigation" />
|
||||||
<include app:graph="@navigation/feature_setting_navigation" />
|
<include app:graph="@navigation/feature_common_parent_child_navigation" />
|
||||||
|
<include app:graph="@navigation/feature_common_child_child_navigation" />
|
||||||
|
<include app:graph="@navigation/feature_wallet_parent_navigation" />
|
||||||
|
<include app:graph="@navigation/feature_wallet_child_navigation" />
|
||||||
</navigation>
|
</navigation>
|
4
app/src/main/res/values/ic_launcher_background.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#F1DEDE</color>
|
||||||
|
</resources>
|
|
@ -1,4 +1,10 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
buildscript {
|
||||||
|
dependencies {
|
||||||
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7" // TODO: カタログと差異が出ないようにする
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.androidApplication) apply false
|
alias(libs.plugins.androidApplication) apply false
|
||||||
id 'com.google.dagger.hilt.android' version '2.44' apply false
|
id 'com.google.dagger.hilt.android' version '2.44' apply false
|
||||||
|
|
|
@ -31,7 +31,7 @@ public interface ChildData {
|
||||||
* 子ユーザー情報更新
|
* 子ユーザー情報更新
|
||||||
* @param child 子ユーザー情報
|
* @param child 子ユーザー情報
|
||||||
*/
|
*/
|
||||||
void updateChild(ChildModel child);
|
CompletableFuture<ChildModel> updateChild(ChildModel child);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 子ユーザー追加
|
* 子ユーザー追加
|
||||||
|
@ -43,7 +43,7 @@ public interface ChildData {
|
||||||
* 子ユーザー削除
|
* 子ユーザー削除
|
||||||
* @param childId 子ID
|
* @param childId 子ID
|
||||||
*/
|
*/
|
||||||
void removeChild(String childId);
|
CompletableFuture<Void> removeChild(String childId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 子ユーザーログインコード発行
|
* 子ユーザーログインコード発行
|
||||||
|
|
|
@ -5,11 +5,12 @@ import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
||||||
import one.nem.kidshift.model.ChildModel;
|
import one.nem.kidshift.model.ChildModel;
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
import one.nem.kidshift.model.ParentModel;
|
import one.nem.kidshift.model.ParentModel;
|
||||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* データの同期など, ユーザーからの操作に基づかない処理を行う
|
* データの同期などを提供する内部ユーティリティ
|
||||||
*/
|
*/
|
||||||
public interface KSActions {
|
public interface KSActions {
|
||||||
|
|
||||||
|
@ -25,4 +26,9 @@ public interface KSActions {
|
||||||
*/
|
*/
|
||||||
CompletableFuture<ParentModel> syncParent();
|
CompletableFuture<ParentModel> syncParent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 履歴情報同期
|
||||||
|
*/
|
||||||
|
CompletableFuture<List<HistoryModel>> syncHistory(String childId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,22 @@ public interface ParentData {
|
||||||
*/
|
*/
|
||||||
CompletableFuture<ParentModel> getParent(ParentModelCallback callback);
|
CompletableFuture<ParentModel> getParent(ParentModelCallback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 親ユーザー情報取得
|
||||||
|
* @return 親ユーザー情報
|
||||||
|
*/
|
||||||
|
CompletableFuture<ParentModel> getParentDirect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 親ユーザー情報取得
|
||||||
|
* @return 親ユーザー情報
|
||||||
|
*/
|
||||||
|
CompletableFuture<ParentModel> getParentCache();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 親ユーザー情報更新
|
* 親ユーザー情報更新
|
||||||
* @param parent 親ユーザー情報
|
* @param parent 親ユーザー情報
|
||||||
*/
|
*/
|
||||||
void updateParent(ParentModel parent);
|
CompletableFuture<Void> updateParent(ParentModel parent);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
package one.nem.kidshift.data;
|
package one.nem.kidshift.data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
|
|
||||||
public interface RewardData {
|
public interface RewardData {
|
||||||
/**
|
/**
|
||||||
* 現時点の合計報酬額を取得する
|
* 現時点の合計報酬額を取得する
|
||||||
* @return Integer 合計報酬額
|
* @return Integer 合計報酬額
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Integer> getTotalReward();
|
CompletableFuture<Integer> getTotalReward(String childId);
|
||||||
|
|
||||||
|
CompletableFuture<List<HistoryModel>> getRewardHistoryList();
|
||||||
|
|
||||||
|
CompletableFuture<List<HistoryModel>> getRewardHistoryList(String childId);
|
||||||
|
|
||||||
|
CompletableFuture<Void> payReward(String historyId);
|
||||||
|
|
||||||
|
CompletableFuture<Void> payReward(List<String> historyIds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,9 @@ public interface UserSettings {
|
||||||
|
|
||||||
boolean isChildMode();
|
boolean isChildMode();
|
||||||
void setChildMode(boolean childMode);
|
void setChildMode(boolean childMode);
|
||||||
|
|
||||||
|
String getChildId();
|
||||||
|
void setChildId(String childId);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SharedPrefCache {
|
interface SharedPrefCache {
|
||||||
|
|
|
@ -36,7 +36,21 @@ public class ChildDataImpl implements ChildData {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<ChildModel> getChild(String childId) {
|
public CompletableFuture<ChildModel> getChild(String childId) {
|
||||||
return null;
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
Call<ChildResponse> call = kidShiftApiService.getChild(childId);
|
||||||
|
try {
|
||||||
|
Response<ChildResponse> response = call.execute();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
assert response.body() != null;
|
||||||
|
logger.info("子供取得成功(childId: " + response.body().getId() + ")");
|
||||||
|
return ChildModelConverter.childResponseToChildModel(response.body());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("HTTP Status: " + response.code());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -94,8 +108,22 @@ public class ChildDataImpl implements ChildData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateChild(ChildModel child) {
|
public CompletableFuture<ChildModel> updateChild(ChildModel child) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
Call<ChildResponse> call = kidShiftApiService.updateChild(ChildModelConverter.childModelToChildAddRequest(child), child.getId());
|
||||||
|
try {
|
||||||
|
Response<ChildResponse> response = call.execute();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
assert response.body() != null;
|
||||||
|
logger.info("子供更新成功(childId: " + response.body().getId() + ")");
|
||||||
|
return ChildModelConverter.childResponseToChildModel(response.body());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("HTTP Status: " + response.code());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -118,8 +146,21 @@ public class ChildDataImpl implements ChildData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeChild(String childId) {
|
public CompletableFuture<Void> removeChild(String childId) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
Call<Void> call = kidShiftApiService.removeChild(childId);
|
||||||
|
try {
|
||||||
|
Response<Void> response = call.execute();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
logger.info("子供削除成功(childId: " + childId + ")");
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("HTTP Status: " + response.code());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,12 +10,15 @@ import one.nem.kidshift.data.UserSettings;
|
||||||
import one.nem.kidshift.data.retrofit.KidShiftApiService;
|
import one.nem.kidshift.data.retrofit.KidShiftApiService;
|
||||||
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
|
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.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.ParentModelConverter;
|
||||||
import one.nem.kidshift.data.retrofit.model.converter.TaskModelConverter;
|
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.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.retrofit.model.task.TaskListResponse;
|
||||||
import one.nem.kidshift.data.room.utils.CacheWrapper;
|
import one.nem.kidshift.data.room.utils.CacheWrapper;
|
||||||
import one.nem.kidshift.model.ChildModel;
|
import one.nem.kidshift.model.ChildModel;
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
import one.nem.kidshift.model.ParentModel;
|
import one.nem.kidshift.model.ParentModel;
|
||||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||||
import one.nem.kidshift.utils.KSLogger;
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
@ -61,7 +64,7 @@ public class KSActionsImpl implements KSActions {
|
||||||
return fetchChildListAsync().thenCombine(fetchTaskListAsync(), (childListResponse, taskListResponse) -> {
|
return fetchChildListAsync().thenCombine(fetchTaskListAsync(), (childListResponse, taskListResponse) -> {
|
||||||
Thread cacheThread = new Thread(() -> {
|
Thread cacheThread = new Thread(() -> {
|
||||||
logger.debug("キャッシュ更新スレッド開始(スレッドID: " + Thread.currentThread().getId() + ")");
|
logger.debug("キャッシュ更新スレッド開始(スレッドID: " + Thread.currentThread().getId() + ")");
|
||||||
cacheWrapper.updateCache(ChildModelConverter.childListResponseToChildModelList(childListResponse),
|
cacheWrapper.updateChildTaskCache(ChildModelConverter.childListResponseToChildModelList(childListResponse),
|
||||||
TaskModelConverter.taskListResponseToTaskItemModelList(taskListResponse)).join();
|
TaskModelConverter.taskListResponseToTaskItemModelList(taskListResponse)).join();
|
||||||
logger.info("キャッシュ更新完了");
|
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, true); // TODO: containPaidを引数に
|
||||||
|
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: キャッシュ更新
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,21 +8,26 @@ import one.nem.kidshift.data.KSActions;
|
||||||
import one.nem.kidshift.data.ParentData;
|
import one.nem.kidshift.data.ParentData;
|
||||||
import one.nem.kidshift.data.UserSettings;
|
import one.nem.kidshift.data.UserSettings;
|
||||||
import one.nem.kidshift.data.retrofit.KidShiftApiService;
|
import one.nem.kidshift.data.retrofit.KidShiftApiService;
|
||||||
|
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
|
||||||
|
import one.nem.kidshift.data.retrofit.model.parent.ParentRenameRequest;
|
||||||
import one.nem.kidshift.model.ParentModel;
|
import one.nem.kidshift.model.ParentModel;
|
||||||
import one.nem.kidshift.model.callback.ParentModelCallback;
|
import one.nem.kidshift.model.callback.ParentModelCallback;
|
||||||
import one.nem.kidshift.utils.KSLogger;
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
import retrofit2.Call;
|
||||||
|
|
||||||
public class ParentDataImpl implements ParentData {
|
public class ParentDataImpl implements ParentData {
|
||||||
|
|
||||||
private final UserSettings userSettings;
|
private final UserSettings userSettings;
|
||||||
|
private final KidShiftApiService kidShiftApiService;
|
||||||
|
|
||||||
private final KSLogger logger;
|
private final KSLogger logger;
|
||||||
|
|
||||||
private final KSActions ksActions;
|
private final KSActions ksActions;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ParentDataImpl(KidShiftApiService kidshiftApiService, UserSettings userSettings, KSLoggerFactory ksLoggerFactory, KSActions ksActions) {
|
public ParentDataImpl(KidShiftApiService kidShiftApiService, UserSettings userSettings, KSLoggerFactory ksLoggerFactory, KSActions ksActions) {
|
||||||
|
this.kidShiftApiService = kidShiftApiService;
|
||||||
this.userSettings = userSettings;
|
this.userSettings = userSettings;
|
||||||
this.logger = ksLoggerFactory.create("ParentDataImpl");
|
this.logger = ksLoggerFactory.create("ParentDataImpl");
|
||||||
this.ksActions = ksActions;
|
this.ksActions = ksActions;
|
||||||
|
@ -46,8 +51,27 @@ public class ParentDataImpl implements ParentData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateParent(ParentModel parent) {
|
public CompletableFuture<ParentModel> getParentDirect() {
|
||||||
|
return ksActions.syncParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<ParentModel> getParentCache() {
|
||||||
|
return CompletableFuture.supplyAsync(() -> userSettings.getCache().getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> updateParent(ParentModel parent) {
|
||||||
|
Call<ParentInfoResponse> call = kidShiftApiService.renameParent(new ParentRenameRequest(parent.getName()));
|
||||||
|
try {
|
||||||
|
ParentInfoResponse response = call.execute().body();
|
||||||
|
if (response == null) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,85 @@
|
||||||
|
package one.nem.kidshift.data.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import one.nem.kidshift.data.ChildData;
|
||||||
|
import one.nem.kidshift.data.KSActions;
|
||||||
|
import one.nem.kidshift.data.RewardData;
|
||||||
|
import one.nem.kidshift.data.UserSettings;
|
||||||
|
import one.nem.kidshift.data.retrofit.KidShiftApiService;
|
||||||
|
import one.nem.kidshift.data.room.utils.CacheWrapper;
|
||||||
|
import one.nem.kidshift.model.ChildModel;
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
import retrofit2.Call;
|
||||||
|
|
||||||
|
public class RewardDataImpl implements RewardData {
|
||||||
|
|
||||||
|
private final UserSettings userSettings;
|
||||||
|
private final KSActions ksActions;
|
||||||
|
private final CacheWrapper cacheWrapper;
|
||||||
|
private final KSLogger logger;
|
||||||
|
private final ChildData childData;
|
||||||
|
private final KidShiftApiService kidShiftApiService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public RewardDataImpl(KSLoggerFactory ksLoggerFactory, CacheWrapper cacheWrapper, UserSettings userSettings, KSActions ksActions, ChildData childData, KidShiftApiService kidShiftApiService) {
|
||||||
|
this.userSettings = userSettings;
|
||||||
|
this.ksActions = ksActions;
|
||||||
|
this.cacheWrapper = cacheWrapper;
|
||||||
|
this.childData = childData;
|
||||||
|
this.kidShiftApiService = kidShiftApiService;
|
||||||
|
this.logger = ksLoggerFactory.create("RewardDataImpl");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Integer> getTotalReward(String childId) { // TODO: localCacheを使う
|
||||||
|
return CompletableFuture.supplyAsync(() -> ksActions.syncHistory(childId).join().stream().mapToInt(HistoryModel::getReward).sum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<HistoryModel>> getRewardHistoryList() { // TODO: localCacheを使う
|
||||||
|
List<HistoryModel> historyModels = new ArrayList<>();
|
||||||
|
return childData.getChildListDirect().thenAccept(childModels -> {
|
||||||
|
childModels.forEach(childModel -> {
|
||||||
|
historyModels.addAll(ksActions.syncHistory(childModel.getId()).join());
|
||||||
|
});
|
||||||
|
}).thenApply(v -> historyModels);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<HistoryModel>> getRewardHistoryList(String childId) { // TODO: localCacheを使う
|
||||||
|
return CompletableFuture.supplyAsync(() -> ksActions.syncHistory(childId).join());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> payReward(String historyId) {
|
||||||
|
return CompletableFuture.runAsync(() -> {
|
||||||
|
Call<Void> call = kidShiftApiService.payHistory(historyId, true);
|
||||||
|
try {
|
||||||
|
call.execute();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Failed to pay reward : " + e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> payReward(List<String> historyIds) {
|
||||||
|
return CompletableFuture.runAsync(() -> {
|
||||||
|
historyIds.forEach(historyId -> { // TODO: API側でリストに対応する
|
||||||
|
Call<Void> call = kidShiftApiService.payHistory(historyId, true);
|
||||||
|
try {
|
||||||
|
call.execute();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Failed to pay reward : " + e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,6 +77,7 @@ public class UserSettingsImpl implements UserSettings {
|
||||||
boolean loggedIn;
|
boolean loggedIn;
|
||||||
String accessToken;
|
String accessToken;
|
||||||
boolean childMode;
|
boolean childMode;
|
||||||
|
String childId;
|
||||||
|
|
||||||
AppCommonSettingImpl() {
|
AppCommonSettingImpl() {
|
||||||
sharedPrefUtils = sharedPrefUtilsFactory.create("user_settings");
|
sharedPrefUtils = sharedPrefUtilsFactory.create("user_settings");
|
||||||
|
@ -85,10 +86,12 @@ public class UserSettingsImpl implements UserSettings {
|
||||||
loggedIn = appCommonSetting.isLoggedIn();
|
loggedIn = appCommonSetting.isLoggedIn();
|
||||||
accessToken = appCommonSetting.getAccessToken().isEmpty() ? "" : appCommonSetting.getAccessToken();
|
accessToken = appCommonSetting.getAccessToken().isEmpty() ? "" : appCommonSetting.getAccessToken();
|
||||||
childMode = appCommonSetting.isChildMode();
|
childMode = appCommonSetting.isChildMode();
|
||||||
|
childId = appCommonSetting.getChildId().isEmpty() ? "" : appCommonSetting.getChildId();
|
||||||
} else {
|
} else {
|
||||||
loggedIn = false;
|
loggedIn = false;
|
||||||
accessToken = "";
|
accessToken = "";
|
||||||
childMode = false;
|
childMode = false;
|
||||||
|
childId = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +131,17 @@ public class UserSettingsImpl implements UserSettings {
|
||||||
this.childMode = childMode;
|
this.childMode = childMode;
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChildId() {
|
||||||
|
return childId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChildId(String childId) {
|
||||||
|
this.childId = childId;
|
||||||
|
save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ApiSettingImpl implements UserSettings.ApiSetting {
|
public class ApiSettingImpl implements UserSettings.ApiSetting {
|
||||||
|
|
|
@ -4,11 +4,12 @@ import dagger.Binds;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.hilt.InstallIn;
|
import dagger.hilt.InstallIn;
|
||||||
import dagger.hilt.android.components.FragmentComponent;
|
import dagger.hilt.android.components.FragmentComponent;
|
||||||
|
import dagger.hilt.components.SingletonComponent;
|
||||||
import one.nem.kidshift.data.ParentData;
|
import one.nem.kidshift.data.ParentData;
|
||||||
import one.nem.kidshift.data.impl.ParentDataImpl;
|
import one.nem.kidshift.data.impl.ParentDataImpl;
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(FragmentComponent.class)
|
@InstallIn(SingletonComponent.class)
|
||||||
public abstract class ParentDataModule {
|
public abstract class ParentDataModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
|
|
|
@ -5,12 +5,12 @@ import dagger.Module;
|
||||||
import dagger.hilt.InstallIn;
|
import dagger.hilt.InstallIn;
|
||||||
import dagger.hilt.android.components.FragmentComponent;
|
import dagger.hilt.android.components.FragmentComponent;
|
||||||
import one.nem.kidshift.data.RewardData;
|
import one.nem.kidshift.data.RewardData;
|
||||||
import one.nem.kidshift.data.impl.RewardDataDummyImpl;
|
import one.nem.kidshift.data.impl.RewardDataImpl;
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(FragmentComponent.class)
|
@InstallIn(FragmentComponent.class)
|
||||||
abstract public class RewardDataDummyModule {
|
public abstract class RewardDataModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
public abstract RewardData bindRewardData(RewardDataDummyImpl rewardDataDummyImpl);
|
public abstract RewardData bindRewardData(RewardDataImpl rewardDataImpl);
|
||||||
}
|
}
|
|
@ -5,9 +5,13 @@ import one.nem.kidshift.data.retrofit.model.child.ChildAddRequest;
|
||||||
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
|
import one.nem.kidshift.data.retrofit.model.child.ChildListResponse;
|
||||||
import one.nem.kidshift.data.retrofit.model.child.ChildLoginCodeResponse;
|
import one.nem.kidshift.data.retrofit.model.child.ChildLoginCodeResponse;
|
||||||
import one.nem.kidshift.data.retrofit.model.child.ChildResponse;
|
import one.nem.kidshift.data.retrofit.model.child.ChildResponse;
|
||||||
|
import one.nem.kidshift.data.retrofit.model.child.auth.ChildAuthRequest;
|
||||||
|
import one.nem.kidshift.data.retrofit.model.child.auth.ChildAuthResponse;
|
||||||
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
|
import one.nem.kidshift.data.retrofit.model.parent.ParentInfoResponse;
|
||||||
|
import one.nem.kidshift.data.retrofit.model.parent.ParentRenameRequest;
|
||||||
import one.nem.kidshift.data.retrofit.model.parent.auth.ParentAuthRequest;
|
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.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.TaskAddRequest;
|
||||||
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
import one.nem.kidshift.data.retrofit.model.task.TaskListResponse;
|
||||||
import one.nem.kidshift.data.retrofit.model.task.TaskResponse;
|
import one.nem.kidshift.data.retrofit.model.task.TaskResponse;
|
||||||
|
@ -42,6 +46,23 @@ public interface KidShiftApiService {
|
||||||
@POST("/parent/auth/register")
|
@POST("/parent/auth/register")
|
||||||
Call<ParentAuthResponse> parentRegister(@Body ParentAuthRequest request);
|
Call<ParentAuthResponse> parentRegister(@Body ParentAuthRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保護者情報更新処理
|
||||||
|
* @param request ParentRenameRequest
|
||||||
|
* @return ParentInfoResponse
|
||||||
|
*/
|
||||||
|
@PUT("/parent/account")
|
||||||
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
|
Call<ParentInfoResponse> renameParent(@Body ParentRenameRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子供ログイン処理
|
||||||
|
* @param request ChildAuthRequest
|
||||||
|
* @return ChildAuthResponse
|
||||||
|
*/
|
||||||
|
@POST("/child/auth/login")
|
||||||
|
Call<ChildAuthResponse> childLogin(@Body ChildAuthRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保護者アカウント情報取得処理
|
* 保護者アカウント情報取得処理
|
||||||
* @return ParentInfoResponse
|
* @return ParentInfoResponse
|
||||||
|
@ -56,7 +77,7 @@ public interface KidShiftApiService {
|
||||||
* タスク一覧取得
|
* タスク一覧取得
|
||||||
* @return TaskListResponse
|
* @return TaskListResponse
|
||||||
*/
|
*/
|
||||||
@GET("/parent/task")
|
@GET("/task")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<TaskListResponse> getTasks();
|
Call<TaskListResponse> getTasks();
|
||||||
|
|
||||||
|
@ -65,7 +86,7 @@ public interface KidShiftApiService {
|
||||||
* @param request TaskAddRequest
|
* @param request TaskAddRequest
|
||||||
* @return TaskResponse
|
* @return TaskResponse
|
||||||
*/
|
*/
|
||||||
@POST("/parent/task")
|
@POST("/task")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<TaskResponse> addTask(@Body TaskAddRequest request);
|
Call<TaskResponse> addTask(@Body TaskAddRequest request);
|
||||||
|
|
||||||
|
@ -75,7 +96,7 @@ public interface KidShiftApiService {
|
||||||
* @param id タスクID
|
* @param id タスクID
|
||||||
* @return TaskResponse
|
* @return TaskResponse
|
||||||
*/
|
*/
|
||||||
@PUT("/parent/task/{id}")
|
@PUT("/task/{id}")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<TaskResponse> updateTask(@Body TaskAddRequest request, @Path("id") String id);
|
Call<TaskResponse> updateTask(@Body TaskAddRequest request, @Path("id") String id);
|
||||||
|
|
||||||
|
@ -84,7 +105,7 @@ public interface KidShiftApiService {
|
||||||
* @param id タスクID
|
* @param id タスクID
|
||||||
* @return Void
|
* @return Void
|
||||||
*/
|
*/
|
||||||
@DELETE("/parent/task/{id}")
|
@DELETE("/task/{id}")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<Void> removeTask(@Path("id") String id); // TODO-rca: OK responseをパース
|
Call<Void> removeTask(@Path("id") String id); // TODO-rca: OK responseをパース
|
||||||
|
|
||||||
|
@ -93,7 +114,7 @@ public interface KidShiftApiService {
|
||||||
* @param id タスクID
|
* @param id タスクID
|
||||||
* @return TaskResponse
|
* @return TaskResponse
|
||||||
*/
|
*/
|
||||||
@GET("/parent/task/{id}")
|
@GET("/task/{id}")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<TaskResponse> getTask(@Path("id") String id);
|
Call<TaskResponse> getTask(@Path("id") String id);
|
||||||
|
|
||||||
|
@ -102,7 +123,7 @@ public interface KidShiftApiService {
|
||||||
* @param id タスクID
|
* @param id タスクID
|
||||||
* @return Void
|
* @return Void
|
||||||
*/
|
*/
|
||||||
@POST("/parent/task/{id}/complete")
|
@POST("/task/{id}/complete")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<Void> completeTask(@Path("id") String id, @Query("childId") String childId);
|
Call<Void> completeTask(@Path("id") String id, @Query("childId") String childId);
|
||||||
|
|
||||||
|
@ -112,26 +133,61 @@ public interface KidShiftApiService {
|
||||||
* 子供一覧取得
|
* 子供一覧取得
|
||||||
* @return ChildListResponse
|
* @return ChildListResponse
|
||||||
*/
|
*/
|
||||||
@GET("/parent/child")
|
@GET("/child")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<ChildListResponse> getChildList();
|
Call<ChildListResponse> getChildList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子供情報取得
|
||||||
|
* @param id 子供ID
|
||||||
|
* @return ChildResponse
|
||||||
|
*/
|
||||||
|
@GET("/child/{id}")
|
||||||
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
|
Call<ChildResponse> getChild(@Path("id") String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 子供追加
|
* 子供追加
|
||||||
* @param request ChildAddRequest
|
* @param request ChildAddRequest
|
||||||
* @return ChildResponse
|
* @return ChildResponse
|
||||||
*/
|
*/
|
||||||
@POST("/parent/child")
|
@POST("/child")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<ChildResponse> addChild(@Body ChildAddRequest request);
|
Call<ChildResponse> addChild(@Body ChildAddRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子供更新
|
||||||
|
* @param request ChildAddRequest
|
||||||
|
* @param id 子供ID
|
||||||
|
* @return ChildResponse
|
||||||
|
*/
|
||||||
|
@PUT("/child/{id}")
|
||||||
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
|
Call<ChildResponse> updateChild(@Body ChildAddRequest request, @Path("id") String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子供削除
|
||||||
|
* @param id 子供ID
|
||||||
|
* @return Void
|
||||||
|
*/
|
||||||
|
@DELETE("/child/{id}")
|
||||||
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
|
Call<Void> removeChild(@Path("id") String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 子供ログインコード発行
|
* 子供ログインコード発行
|
||||||
* @param id 子供ID
|
* @param id 子供ID
|
||||||
* @return ChildLoginCodeResponse
|
* @return ChildLoginCodeResponse
|
||||||
*/
|
*/
|
||||||
@GET("/parent/child/{id}/login")
|
@GET("/child/{id}/login")
|
||||||
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
Call<ChildLoginCodeResponse> issueLoginCode(@Path("id") String id);
|
Call<ChildLoginCodeResponse> issueLoginCode(@Path("id") String id);
|
||||||
|
|
||||||
|
@GET("/task/history/{childId}")
|
||||||
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
|
Call<HistoryListResponse> getHistory(@Path("childId") String childId, @Query("containPaid") boolean containPaid);
|
||||||
|
|
||||||
|
@POST("/task/history/{historyId}/paid")
|
||||||
|
@Headers(AuthorizationInterceptor.HEADER_PLACEHOLDER)
|
||||||
|
Call<Void> payHistory(@Path("historyId") String historyId, @Query("isPaid") boolean isPaid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package one.nem.kidshift.data.retrofit.model.child.auth;
|
||||||
|
|
||||||
|
public class ChildAuthRequest {
|
||||||
|
private String loginCode;
|
||||||
|
|
||||||
|
public ChildAuthRequest(String loginCode) {
|
||||||
|
this.loginCode = loginCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLoginCode() {
|
||||||
|
return loginCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginCode(String loginCode) {
|
||||||
|
this.loginCode = loginCode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package one.nem.kidshift.data.retrofit.model.child.auth;
|
||||||
|
|
||||||
|
public class ChildAuthResponse {
|
||||||
|
private String accessToken;
|
||||||
|
private String childId;
|
||||||
|
|
||||||
|
public ChildAuthResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChildAuthResponse(String accessToken, String childId) {
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
this.childId = childId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChildId() {
|
||||||
|
return childId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildId(String childId) {
|
||||||
|
this.childId = childId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccessToken() {
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessToken(String accessToken) {
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
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());
|
||||||
|
historyModel.setPaid(historyResponse.isPaid());
|
||||||
|
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());
|
||||||
|
historyResponse.setPaid(historyModel.isPaid());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ public class ParentModelConverter {
|
||||||
* @return ParentModel
|
* @return ParentModel
|
||||||
*/
|
*/
|
||||||
public static ParentModel parentInfoResponseToParentModel(ParentInfoResponse parentInfoResponse) {
|
public static ParentModel parentInfoResponseToParentModel(ParentInfoResponse parentInfoResponse) {
|
||||||
return new ParentModel(parentInfoResponse.getId(), parentInfoResponse.getDisplayName(), parentInfoResponse.getEmail());
|
return new ParentModel(parentInfoResponse.getId(), parentInfoResponse.getDisplay_name(), parentInfoResponse.getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,18 +4,18 @@ public class ParentInfoResponse {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String email;
|
private String email;
|
||||||
private String displayName;
|
private String display_name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* コンストラクタ (全プロパティ)
|
* コンストラクタ (全プロパティ)
|
||||||
* @param id 親ID
|
* @param id 親ID
|
||||||
* @param email メールアドレス
|
* @param email メールアドレス
|
||||||
* @param displayName 表示名
|
* @param display_name 表示名
|
||||||
*/
|
*/
|
||||||
public ParentInfoResponse(String id, String email, String displayName) {
|
public ParentInfoResponse(String id, String email, String display_name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.displayName = displayName;
|
this.display_name = display_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -26,8 +26,8 @@ public class ParentInfoResponse {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDisplayName() {
|
public String getDisplay_name() {
|
||||||
return displayName;
|
return display_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(String id) {
|
public void setId(String id) {
|
||||||
|
@ -38,7 +38,7 @@ public class ParentInfoResponse {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisplayName(String displayName) {
|
public void setDisplay_name(String display_name) {
|
||||||
this.displayName = displayName;
|
this.display_name = display_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package one.nem.kidshift.data.retrofit.model.parent;
|
||||||
|
|
||||||
|
public class ParentRenameRequest {
|
||||||
|
private String displayName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* コンストラクタ (全プロパティ)
|
||||||
|
* @param displayName 表示名
|
||||||
|
*/
|
||||||
|
public ParentRenameRequest(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisplayName(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
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;
|
||||||
|
private boolean isPaid;
|
||||||
|
|
||||||
|
public HistoryBaseItem(String id, String taskId, String childId, Date registeredAt, boolean isPaid) {
|
||||||
|
this.id = id;
|
||||||
|
this.taskId = taskId;
|
||||||
|
this.childId = childId;
|
||||||
|
this.registeredAt = registeredAt;
|
||||||
|
this.isPaid = isPaid;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPaid() {
|
||||||
|
return isPaid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPaid(boolean isPaid) {
|
||||||
|
this.isPaid = isPaid;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 androidx.room.RoomDatabase;
|
||||||
|
|
||||||
import one.nem.kidshift.data.room.dao.ChildCacheDao;
|
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.TaskCacheDao;
|
||||||
import one.nem.kidshift.data.room.dao.TaskChildLinkageDao;
|
import one.nem.kidshift.data.room.dao.TaskChildLinkageDao;
|
||||||
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
|
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.TaskCacheEntity;
|
||||||
import one.nem.kidshift.data.room.entity.TaskChildLinkageEntity;
|
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 class KidShiftDatabase extends RoomDatabase {
|
||||||
|
|
||||||
public abstract ChildCacheDao childCacheDao();
|
public abstract ChildCacheDao childCacheDao();
|
||||||
|
@ -19,4 +21,6 @@ public abstract class KidShiftDatabase extends RoomDatabase {
|
||||||
|
|
||||||
public abstract TaskChildLinkageDao taskChildLinkageDao();
|
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.Module;
|
||||||
import dagger.hilt.InstallIn;
|
import dagger.hilt.InstallIn;
|
||||||
import dagger.hilt.components.SingletonComponent;
|
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.KidShiftDatabase;
|
||||||
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
|
import one.nem.kidshift.data.room.entity.ChildCacheEntity;
|
||||||
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
|
import one.nem.kidshift.data.room.entity.TaskCacheEntity;
|
||||||
import one.nem.kidshift.data.room.entity.TaskChildLinkageEntity;
|
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.ChildCacheConverter;
|
||||||
|
import one.nem.kidshift.data.room.utils.converter.HistoryCacheConverter;
|
||||||
import one.nem.kidshift.data.room.utils.converter.TaskCacheConverter;
|
import one.nem.kidshift.data.room.utils.converter.TaskCacheConverter;
|
||||||
import one.nem.kidshift.model.ChildModel;
|
import one.nem.kidshift.model.ChildModel;
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||||
import one.nem.kidshift.utils.KSLogger;
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
@ -39,7 +43,7 @@ public class CacheWrapper {
|
||||||
* @param taskList タスクリスト
|
* @param taskList タスクリスト
|
||||||
* @return CompletableFuture
|
* @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(() -> {
|
return CompletableFuture.runAsync(() -> {
|
||||||
logger.debug("Updating cache");
|
logger.debug("Updating cache");
|
||||||
insertChildList(childList).join();
|
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に挿入する
|
* 子供リストをDBに挿入する
|
||||||
* @param childList 子供リスト
|
* @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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,8 @@ dependencies {
|
||||||
implementation libs.material
|
implementation libs.material
|
||||||
implementation libs.navigation.fragment
|
implementation libs.navigation.fragment
|
||||||
implementation libs.navigation.ui
|
implementation libs.navigation.ui
|
||||||
|
implementation libs.activity
|
||||||
|
implementation libs.constraintlayout
|
||||||
testImplementation libs.junit
|
testImplementation libs.junit
|
||||||
androidTestImplementation libs.ext.junit
|
androidTestImplementation libs.ext.junit
|
||||||
androidTestImplementation libs.espresso.core
|
androidTestImplementation libs.espresso.core
|
||||||
|
@ -48,4 +50,5 @@ dependencies {
|
||||||
implementation project(':model')
|
implementation project(':model')
|
||||||
implementation project(':utils')
|
implementation project(':utils')
|
||||||
implementation project(':data')
|
implementation project(':data')
|
||||||
|
implementation project(':shared')
|
||||||
}
|
}
|
|
@ -1,4 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity
|
||||||
|
android:name=".ChildManageMainActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -90,24 +90,24 @@ public class ChildMainFragment extends Fragment {
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
//
|
||||||
logger.addTag("ChildMainFragment");
|
// logger.addTag("ChildMainFragment");
|
||||||
|
//
|
||||||
Integer reward = rewardData.getTotalReward().join();
|
// Integer reward = rewardData.getTotalReward().join();
|
||||||
|
//
|
||||||
logger.debug("取得したデータ: " + reward);
|
// logger.debug("取得したデータ: " + reward);
|
||||||
|
//
|
||||||
Calendar cl = Calendar.getInstance();
|
// Calendar cl = Calendar.getInstance();
|
||||||
TextView tr = view.findViewById(R.id.totalReward);
|
// TextView tr = view.findViewById(R.id.totalReward);
|
||||||
TextView dv = view.findViewById(R.id.dateView);
|
// TextView dv = view.findViewById(R.id.dateView);
|
||||||
Date date = new Date();
|
// Date date = new Date();
|
||||||
|
//
|
||||||
|
//
|
||||||
NumberFormat nf = NumberFormat.getNumberInstance();
|
// NumberFormat nf = NumberFormat.getNumberInstance();
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat();
|
// SimpleDateFormat sdf = new SimpleDateFormat();
|
||||||
sdf.applyPattern("yyyy年MM月");
|
// sdf.applyPattern("yyyy年MM月");
|
||||||
|
//
|
||||||
dv.setText(sdf.format(cl.getTime()) + " お小遣い総額");
|
// dv.setText(sdf.format(cl.getTime()) + " お小遣い総額");
|
||||||
tr.setText("¥" + nf.format(reward).toString());
|
// tr.setText("¥" + nf.format(reward).toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
package one.nem.kidshift.feature.child;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.print.PrintAttributes;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
|
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.feature.child.adapter.ChildListAdapter;
|
||||||
|
import one.nem.kidshift.model.ChildModel;
|
||||||
|
import one.nem.kidshift.model.callback.ChildModelCallback;
|
||||||
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
public class ChildManageMainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ChildData childData;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
KSLoggerFactory loggerFactory;
|
||||||
|
|
||||||
|
private KSLogger logger;
|
||||||
|
|
||||||
|
ChildListAdapter childListAdapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
setContentView(R.layout.activity_child_manage_main);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
|
logger = loggerFactory.create("ChildManageMainActivity");
|
||||||
|
|
||||||
|
// ToolBarのセットアップ
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolBar);
|
||||||
|
// タイトル
|
||||||
|
toolbar.setTitle("子供アカウント管理");
|
||||||
|
// 閉じる
|
||||||
|
toolbar.setNavigationIcon(one.nem.kidshift.shared.R.drawable.close_24px);
|
||||||
|
toolbar.setNavigationOnClickListener(v -> finish());
|
||||||
|
// 追加ボタン
|
||||||
|
toolbar.inflateMenu(R.menu.child_manage_main_toolbar_item);
|
||||||
|
toolbar.setOnMenuItemClickListener(item -> {
|
||||||
|
if (item.getItemId() == R.id.add_child_account) {
|
||||||
|
showAddChildDialog();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
RecyclerView recyclerView = findViewById(R.id.childListRecyclerView);
|
||||||
|
childListAdapter = new ChildListAdapter();
|
||||||
|
childListAdapter.setButtonEventCallback(new ChildListAdapter.ButtonEventCallback() {
|
||||||
|
@Override
|
||||||
|
public void onEditButtonClick(ChildModel childModel) {
|
||||||
|
showEditChildDialog(childModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoginButtonClick(ChildModel childModel) {
|
||||||
|
childData.issueLoginCode(childModel.getId()).thenAccept(loginCode -> {
|
||||||
|
logger.debug("ログインコード発行完了: " + loginCode);
|
||||||
|
runOnUiThread(() -> showLoginCodeDialog(loginCode));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
|
recyclerView.setAdapter(childListAdapter);
|
||||||
|
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showLoginCodeDialog(Integer loginCode) {
|
||||||
|
View view = getLayoutInflater().inflate(R.layout.child_login_code_dialog_layout, null);
|
||||||
|
TextView loginCodeTextView = view.findViewById(R.id.loginCode);
|
||||||
|
// loginCodeをStringに変換して4桁 2つに分割してハイフンで繋げる
|
||||||
|
loginCodeTextView.setText(loginCode.toString().substring(0, 4) + "-" + loginCode.toString().substring(4));
|
||||||
|
|
||||||
|
new MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle("ログインコード")
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton("閉じる", (dialog, which) -> dialog.dismiss())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAddChildDialog() {
|
||||||
|
// EditTextを作成
|
||||||
|
EditText childNameEditText = new EditText(this);
|
||||||
|
childNameEditText.setHint("子供の名前");
|
||||||
|
// FrameLayoutに入れる
|
||||||
|
FrameLayout container = new FrameLayout(this);
|
||||||
|
container.addView(childNameEditText);
|
||||||
|
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) childNameEditText.getLayoutParams();
|
||||||
|
params.setMargins(32, 16, 32, 16);
|
||||||
|
childNameEditText.setLayoutParams(params);
|
||||||
|
|
||||||
|
new MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle("子供アカウント追加")
|
||||||
|
.setView(container)
|
||||||
|
.setPositiveButton("追加", (dialog, which) -> {
|
||||||
|
String childName = Objects.requireNonNull(childNameEditText.getText()).toString();
|
||||||
|
if (childName.isEmpty()) {
|
||||||
|
Toast.makeText(this, "名前を入力してください", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
childData.addChild(new ChildModel(childName))
|
||||||
|
.thenRun(this::updateListDirectly);
|
||||||
|
})
|
||||||
|
.setNegativeButton("キャンセル", (dialog, which) -> dialog.dismiss())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showEditChildDialog(ChildModel childModel) {
|
||||||
|
// EditTextを作成
|
||||||
|
EditText childNameEditText = new EditText(this);
|
||||||
|
childNameEditText.setHint("子供の名前");
|
||||||
|
childNameEditText.setText(childModel.getName());
|
||||||
|
// FrameLayoutに入れる
|
||||||
|
FrameLayout container = new FrameLayout(this);
|
||||||
|
container.addView(childNameEditText);
|
||||||
|
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) childNameEditText.getLayoutParams();
|
||||||
|
params.setMargins(32, 16, 32, 16);
|
||||||
|
childNameEditText.setLayoutParams(params);
|
||||||
|
|
||||||
|
new MaterialAlertDialogBuilder(this)
|
||||||
|
.setTitle("子供アカウント編集")
|
||||||
|
.setView(container)
|
||||||
|
.setPositiveButton("保存", (dialog, which) -> {
|
||||||
|
String childName = Objects.requireNonNull(childNameEditText.getText()).toString();
|
||||||
|
if (childName.isEmpty()) {
|
||||||
|
Toast.makeText(this, "名前を入力してください", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
childModel.setName(childName);
|
||||||
|
childData.updateChild(childModel)
|
||||||
|
.thenRun(this::updateListDirectly);
|
||||||
|
})
|
||||||
|
.setNegativeButton("キャンセル", (dialog, which) -> dialog.dismiss())
|
||||||
|
// 削除ボタン
|
||||||
|
.setNeutralButton("削除", (dialog, which) -> { // TODO: 確認ダイアログを表示する
|
||||||
|
childData.removeChild(childModel.getId())
|
||||||
|
.thenRun(this::updateListDirectly);
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private void updateList() {
|
||||||
|
childData.getChildList(new ChildModelCallback() {
|
||||||
|
@Override
|
||||||
|
public void onUnchanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdated(List<ChildModel> childModelList) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed(String message) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}).thenAccept(childListAdapter::setChildList).thenRun(() -> {
|
||||||
|
runOnUiThread(() -> childListAdapter.notifyDataSetChanged());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private void updateListDirectly() {
|
||||||
|
childData.getChildListDirect().thenAccept(childListAdapter::setChildList).thenRun(() -> {
|
||||||
|
runOnUiThread(() -> childListAdapter.notifyDataSetChanged());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package one.nem.kidshift.feature.child.adapter;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import one.nem.kidshift.feature.child.R;
|
||||||
|
import one.nem.kidshift.model.ChildModel;
|
||||||
|
|
||||||
|
public class ChildListAdapter extends RecyclerView.Adapter<ChildListAdapter.ViewHolder>{
|
||||||
|
|
||||||
|
private List<ChildModel> childList;
|
||||||
|
private ButtonEventCallback buttonEventCallback;
|
||||||
|
|
||||||
|
public ChildListAdapter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildList(List<ChildModel> childList) {
|
||||||
|
this.childList = childList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setButtonEventCallback(ButtonEventCallback buttonEventCallback) {
|
||||||
|
this.buttonEventCallback = buttonEventCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ChildListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_child_manage_main, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ChildListAdapter.ViewHolder holder, int position) {
|
||||||
|
ChildModel childModel = childList.get(position);
|
||||||
|
holder.childNameTextView.setText(childModel.getName());
|
||||||
|
holder.editButton.setOnClickListener(v -> {
|
||||||
|
if (buttonEventCallback != null) {
|
||||||
|
buttonEventCallback.onEditButtonClick(childModel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
holder.loginButton.setOnClickListener(v -> {
|
||||||
|
if (buttonEventCallback != null) {
|
||||||
|
buttonEventCallback.onLoginButtonClick(childModel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return childList == null ? 0 : childList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
TextView childNameTextView;
|
||||||
|
Button editButton;
|
||||||
|
Button loginButton;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
childNameTextView = itemView.findViewById(R.id.childNameTextView);
|
||||||
|
editButton = itemView.findViewById(R.id.editButton);
|
||||||
|
loginButton = itemView.findViewById(R.id.loginButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ButtonEventCallback {
|
||||||
|
void onEditButtonClick(ChildModel childModel);
|
||||||
|
void onLoginButtonClick(ChildModel childModel);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?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:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ChildManageMainActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:minHeight="?attr/actionBarSize"
|
||||||
|
android:theme="?attr/actionBarTheme"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/childListRecyclerView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="1dp"
|
||||||
|
android:layout_marginTop="1dp"
|
||||||
|
android:layout_marginEnd="1dp"
|
||||||
|
android:layout_marginBottom="1dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/toolBar" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/loginCode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="30dp"
|
||||||
|
android:paddingBottom="25dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Display3" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginVertical="12dp"
|
||||||
|
android:layout_marginHorizontal="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/childNameTextView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Placeholder"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/linearLayout"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/editButton"
|
||||||
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="編集"
|
||||||
|
android:layout_marginRight="8px"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/loginButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="ログイン"
|
||||||
|
android:layout_marginLeft="8px"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/add_child_account"
|
||||||
|
android:icon="@drawable/add_24px"
|
||||||
|
app:showAsAction="ifRoom"
|
||||||
|
android:title="子供アカウントの追加" />
|
||||||
|
</menu>
|
|
@ -1,6 +1,7 @@
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.androidLibrary)
|
alias(libs.plugins.androidLibrary)
|
||||||
id 'com.google.dagger.hilt.android'
|
id 'com.google.dagger.hilt.android'
|
||||||
|
id 'androidx.navigation.safeargs'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
|
@ -1,21 +1,41 @@
|
||||||
package one.nem.kidshift.feature.common;
|
package one.nem.kidshift.feature.common;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.view.MenuHost;
|
||||||
|
import androidx.core.view.MenuProvider;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.Lifecycle;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.github.sundeepk.compactcalendarview.CompactCalendarView;
|
import com.github.sundeepk.compactcalendarview.CompactCalendarView;
|
||||||
|
import com.github.sundeepk.compactcalendarview.domain.Event;
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
@ -23,13 +43,20 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
import one.nem.kidshift.data.ChildData;
|
import one.nem.kidshift.data.ChildData;
|
||||||
|
import one.nem.kidshift.data.RewardData;
|
||||||
import one.nem.kidshift.data.TaskData;
|
import one.nem.kidshift.data.TaskData;
|
||||||
|
import one.nem.kidshift.data.UserSettings;
|
||||||
import one.nem.kidshift.feature.common.adapter.ChildListItemAdapter;
|
import one.nem.kidshift.feature.common.adapter.ChildListItemAdapter;
|
||||||
import one.nem.kidshift.feature.common.adapter.TaskListItemAdapter;
|
import one.nem.kidshift.feature.common.adapter.TaskListItemAdapter;
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
import one.nem.kidshift.model.callback.TaskItemModelCallback;
|
import one.nem.kidshift.model.callback.TaskItemModelCallback;
|
||||||
import one.nem.kidshift.model.tasks.TaskItemModel;
|
import one.nem.kidshift.model.tasks.TaskItemModel;
|
||||||
|
import one.nem.kidshift.utils.FabManager;
|
||||||
import one.nem.kidshift.utils.KSLogger;
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.RecyclerViewAnimUtils;
|
||||||
|
import one.nem.kidshift.utils.ToolBarManager;
|
||||||
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
import one.nem.kidshift.utils.models.FabEventCallback;
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class CommonHomeFragment extends Fragment {
|
public class CommonHomeFragment extends Fragment {
|
||||||
|
@ -43,14 +70,29 @@ public class CommonHomeFragment extends Fragment {
|
||||||
TaskData taskData;
|
TaskData taskData;
|
||||||
@Inject
|
@Inject
|
||||||
ChildData childData;
|
ChildData childData;
|
||||||
|
@Inject
|
||||||
|
FabManager fabManager;
|
||||||
|
@Inject
|
||||||
|
ToolBarManager toolBarManager;
|
||||||
|
@Inject
|
||||||
|
RewardData rewardData;
|
||||||
|
@Inject
|
||||||
|
RecyclerViewAnimUtils recyclerViewAnimUtils;
|
||||||
|
@Inject
|
||||||
|
UserSettings userSettings;
|
||||||
|
|
||||||
|
|
||||||
private boolean isChildMode;
|
private boolean isChildMode;
|
||||||
private String childId;
|
private String childId;
|
||||||
private KSLogger logger;
|
private KSLogger logger;
|
||||||
|
|
||||||
CompactCalendarView compactCalendarView;
|
CompactCalendarView compactCalendarView;
|
||||||
|
View calendarContainer;
|
||||||
SwipeRefreshLayout swipeRefreshLayout;
|
SwipeRefreshLayout swipeRefreshLayout;
|
||||||
TaskListItemAdapter taskListItemAdapter;
|
TaskListItemAdapter taskListItemAdapter;
|
||||||
|
TextView calendarTitleTextView;
|
||||||
|
ImageButton calendarPrevButton;
|
||||||
|
ImageButton calendarNextButton;
|
||||||
|
|
||||||
public CommonHomeFragment() {
|
public CommonHomeFragment() {
|
||||||
// Required empty public constructor
|
// Required empty public constructor
|
||||||
|
@ -62,9 +104,7 @@ public class CommonHomeFragment extends Fragment {
|
||||||
CommonHomeFragment fragment = new CommonHomeFragment();
|
CommonHomeFragment fragment = new CommonHomeFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putBoolean(ARG_IS_CHILD_MODE, isChildMode);
|
args.putBoolean(ARG_IS_CHILD_MODE, isChildMode);
|
||||||
if (isChildMode) {
|
|
||||||
args.putString(ARG_CHILD_ID, childId);
|
args.putString(ARG_CHILD_ID, childId);
|
||||||
}
|
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
@ -72,11 +112,31 @@ public class CommonHomeFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if (getArguments() != null) {
|
|
||||||
isChildMode = getArguments().getBoolean(ARG_IS_CHILD_MODE);
|
|
||||||
childId = getArguments().getString(ARG_CHILD_ID);
|
|
||||||
}
|
|
||||||
logger = ksLoggerFactory.create("CommonHomeFragment");
|
logger = ksLoggerFactory.create("CommonHomeFragment");
|
||||||
|
|
||||||
|
if (userSettings.getAppCommonSetting().isChildMode()) {
|
||||||
|
logger.debug("子供モードで起動(子供ログイン)");
|
||||||
|
isChildMode = true;
|
||||||
|
childId = userSettings.getAppCommonSetting().getChildId();
|
||||||
|
logger.debug("childId: " + childId);
|
||||||
|
} else {
|
||||||
|
if (getArguments() != null) {
|
||||||
|
isChildMode = getArguments().getBoolean(ARG_IS_CHILD_MODE) && getArguments().getBoolean(ARG_IS_CHILD_MODE);
|
||||||
|
childId = getArguments().getString(ARG_CHILD_ID) != null ? getArguments().getString(ARG_CHILD_ID) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childId != null && !childId.isEmpty()) {
|
||||||
|
isChildMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChildMode) {
|
||||||
|
logger.debug("子供モードで起動");
|
||||||
|
logger.debug("childId: " + childId);
|
||||||
|
} else {
|
||||||
|
logger.debug("保護者モードで起動");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,9 +149,7 @@ public class CommonHomeFragment extends Fragment {
|
||||||
taskListItemAdapter = new TaskListItemAdapter();
|
taskListItemAdapter = new TaskListItemAdapter();
|
||||||
taskListItemAdapter.setCallback((taskId, taskName) -> {
|
taskListItemAdapter.setCallback((taskId, taskName) -> {
|
||||||
if (isChildMode) {
|
if (isChildMode) {
|
||||||
if (showConfirmDialog(taskName)) {
|
showConfirmDialog(taskId, taskName);
|
||||||
taskData.recordTaskCompletion(taskId, childId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
showChildSelectDialog(taskId, taskName);
|
showChildSelectDialog(taskId, taskName);
|
||||||
}
|
}
|
||||||
|
@ -100,39 +158,169 @@ public class CommonHomeFragment extends Fragment {
|
||||||
RecyclerView taskListRecyclerView = view.findViewById(R.id.taskListRecyclerView);
|
RecyclerView taskListRecyclerView = view.findViewById(R.id.taskListRecyclerView);
|
||||||
taskListRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
taskListRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
taskListRecyclerView.setAdapter(taskListItemAdapter);
|
taskListRecyclerView.setAdapter(taskListItemAdapter);
|
||||||
|
taskListRecyclerView.setItemViewCacheSize(10);
|
||||||
|
recyclerViewAnimUtils.setSlideUpAnimation(taskListRecyclerView);
|
||||||
|
|
||||||
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout);
|
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout);
|
||||||
swipeRefreshLayout.setOnRefreshListener(this::updateData);
|
swipeRefreshLayout.setOnRefreshListener(this::updateData);
|
||||||
|
|
||||||
|
calendarTitleTextView = view.findViewById(R.id.calendarTitleTextView);
|
||||||
|
calendarPrevButton = view.findViewById(R.id.calendarPrevButton);
|
||||||
|
calendarNextButton = view.findViewById(R.id.calendarNextButton);
|
||||||
|
calendarContainer = view.findViewById(R.id.calendarContainer);
|
||||||
|
|
||||||
|
initCalender();
|
||||||
|
updateData();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recyclerViewRefresh() {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
taskListItemAdapter.notifyItemRangeRemoved(0, taskListItemAdapter.getItemCount());
|
||||||
|
taskListItemAdapter.notifyItemRangeInserted(0, taskListItemAdapter.getItemCount());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
updateData();
|
if (isChildMode) {
|
||||||
|
setupFabChild();
|
||||||
|
} else {
|
||||||
|
setupFabParent();
|
||||||
|
}
|
||||||
|
setupToolBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean showConfirmDialog(String taskName) {
|
/**
|
||||||
AtomicBoolean selection = new AtomicBoolean(false);
|
* 親モードの場合(=子供モードではない場合)のFABの設定
|
||||||
|
*/
|
||||||
|
private void setupFabParent() {
|
||||||
|
fabManager.show();
|
||||||
|
fabManager.setFabEventCallback(new FabEventCallback() {
|
||||||
|
@Override
|
||||||
|
public void onClicked() {
|
||||||
|
showAddTaskDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLongClicked() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子供モードの場合のFABの設定
|
||||||
|
*/
|
||||||
|
private void setupFabChild() {
|
||||||
|
fabManager.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupToolBar() {
|
||||||
|
if (isChildMode) {
|
||||||
|
toolBarManager.setTitle("ホーム");
|
||||||
|
toolBarManager.setSubtitle("子供ビュー");
|
||||||
|
} else {
|
||||||
|
toolBarManager.setTitle("ホーム");
|
||||||
|
toolBarManager.setSubtitle("保護者ビュー");
|
||||||
|
}
|
||||||
|
MenuHost menuHost = requireActivity();
|
||||||
|
|
||||||
|
menuHost.invalidateMenu();
|
||||||
|
menuHost.addMenuProvider(new MenuProvider() {
|
||||||
|
@Override
|
||||||
|
public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
|
||||||
|
logger.debug("onCreateMenu, インフレート");
|
||||||
|
menu.clear();
|
||||||
|
menuInflater.inflate(R.menu.common_home_toolbar_menu, menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
|
||||||
|
if (menuItem.getItemId() == R.id.toggle_calendar) {
|
||||||
|
if (calendarContainer.getVisibility() == View.VISIBLE) {
|
||||||
|
Animation slideUp = AnimationUtils.loadAnimation(getContext(), one.nem.kidshift.shared.R.anim.slide_up);
|
||||||
|
calendarContainer.startAnimation(slideUp);
|
||||||
|
slideUp.setAnimationListener(new Animation.AnimationListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animation animation) {
|
||||||
|
recyclerViewRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animation animation) {
|
||||||
|
calendarContainer.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animation animation) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Animation slideDown = AnimationUtils.loadAnimation(getContext(), one.nem.kidshift.shared.R.anim.slide_down);
|
||||||
|
calendarContainer.startAnimation(slideDown);
|
||||||
|
slideDown.setAnimationListener(new Animation.AnimationListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animation animation) {
|
||||||
|
calendarContainer.setVisibility(View.VISIBLE);
|
||||||
|
recyclerViewRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animation animation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animation animation) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, this.getViewLifecycleOwner(), Lifecycle.State.RESUMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* タスク完了確認ダイアログを表示 (子供モード用)
|
||||||
|
*
|
||||||
|
* @param taskId タスクID
|
||||||
|
* @param taskName タスク名
|
||||||
|
*/
|
||||||
|
private void showConfirmDialog(String taskId, String taskName) {
|
||||||
new MaterialAlertDialogBuilder(requireContext())
|
new MaterialAlertDialogBuilder(requireContext())
|
||||||
.setTitle("タスクを完了しますか?")
|
.setTitle("タスクを完了しますか?")
|
||||||
.setMessage(taskName + "を完了しますか?")
|
.setMessage(taskName + "を完了しますか?")
|
||||||
.setPositiveButton("はい", (dialog, which) -> {
|
.setPositiveButton("はい", (dialog, which) -> {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
selection.set(true);
|
taskData.recordTaskCompletion(taskId, childId);
|
||||||
})
|
})
|
||||||
.setNegativeButton("いいえ", (dialog, which) -> {
|
.setNegativeButton("いいえ", (dialog, which) -> {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
selection.set(false);
|
taskData.recordTaskCompletion(taskId, childId);
|
||||||
})
|
})
|
||||||
.show();
|
.show();
|
||||||
return selection.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* タスク完了ダイアログ(子供選択画面)を表示 (親モード用)
|
||||||
|
*
|
||||||
|
* @param taskId タスクID
|
||||||
|
* @param taskName タスク名
|
||||||
|
*/
|
||||||
private void showChildSelectDialog(String taskId, String taskName) { // TODO: Assignされている子供かどうかを考慮するように
|
private void showChildSelectDialog(String taskId, String taskName) { // TODO: Assignされている子供かどうかを考慮するように
|
||||||
RecyclerView childListRecyclerView = new RecyclerView(requireContext());
|
RecyclerView childListRecyclerView = new RecyclerView(requireContext());
|
||||||
childListRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
childListRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
childListRecyclerView.setPadding(0, 48, 0, 0);
|
||||||
// TODO: キャッシュから取得する方にする?
|
// TODO: キャッシュから取得する方にする?
|
||||||
childData.getChildListDirect().thenAccept(childModelList -> {
|
childData.getChildListDirect().thenAccept(childModelList -> {
|
||||||
ChildListItemAdapter childListItemAdapter = new ChildListItemAdapter(childModelList);
|
ChildListItemAdapter childListItemAdapter = new ChildListItemAdapter(childModelList);
|
||||||
|
@ -151,43 +339,132 @@ public class CommonHomeFragment extends Fragment {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* タスク情報を更新
|
||||||
|
* @return CompletableFuture<Void>
|
||||||
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private CompletableFuture<Void> updateTaskInfo() { // TODO: updatedの場合の処理など実装
|
private CompletableFuture<Void> updateTaskInfo() { // TODO: updatedの場合の処理など実装
|
||||||
return taskData.getTasks(new TaskItemModelCallback() {
|
return taskData.getTasks(new TaskItemModelCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onUnchanged() {
|
public void onUnchanged() {
|
||||||
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdated(List<TaskItemModel> taskItem) {
|
public void onUpdated(List<TaskItemModel> taskItem) { // Workaround
|
||||||
|
taskListItemAdapter.notifyItemRangeRemoved(0, taskListItemAdapter.getItemCount());
|
||||||
|
taskListItemAdapter.setTaskItemModelList(taskItem);
|
||||||
|
taskListItemAdapter.notifyItemRangeInserted(0, taskItem.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailed(String message) {
|
public void onFailed(String message) {
|
||||||
|
// TODO: ユーザーに丁寧に通知
|
||||||
|
Toast.makeText(requireContext(), "タスク情報の取得に失敗しました", Toast.LENGTH_SHORT).show(); // Workaround
|
||||||
}
|
}
|
||||||
}).thenAccept(taskItemModel -> {
|
}).thenAccept(taskItemModel -> {
|
||||||
taskListItemAdapter.setTaskItemModelList(taskItemModel);
|
|
||||||
requireActivity().runOnUiThread(() -> {
|
requireActivity().runOnUiThread(() -> {
|
||||||
taskListItemAdapter.notifyDataSetChanged();
|
// taskListItemAdapter.notifyItemRangeRemoved(0, taskListItemAdapter.getItemCount());
|
||||||
|
// taskListItemAdapter.setTaskItemModelList(taskItemModel);
|
||||||
|
// taskListItemAdapter.notifyItemRangeInserted(0, taskItemModel.size());
|
||||||
|
taskListItemAdapter.setTaskItemModelList(taskItemModel);
|
||||||
|
taskListItemAdapter.notifyItemRangeChanged(0, taskItemModel.size());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* カレンダーを更新
|
||||||
|
* @return CompletableFuture<Void>
|
||||||
|
*/
|
||||||
private CompletableFuture<Void> updateCalender() {
|
private CompletableFuture<Void> updateCalender() {
|
||||||
// TODO: タスクの完了状況をカレンダーに表示
|
return rewardData.getRewardHistoryList().thenAccept(historyModels -> {
|
||||||
return CompletableFuture.completedFuture(null);
|
historyModels.forEach(historyModel -> {
|
||||||
|
compactCalendarView.addEvent(new Event(Color.RED, historyModel.getRegisteredAt().getTime(), historyModel)); // debug
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateData() {
|
private void initCalender() {
|
||||||
swipeRefreshLayout.setRefreshing(true);
|
compactCalendarView.setListener(new CompactCalendarView.CompactCalendarViewListener() {
|
||||||
CompletableFuture.allOf(updateTaskInfo(), updateCalender()).thenRun(() -> {
|
@Override
|
||||||
// Workaround: リスト更新処理があまりにも重くてアニメーションが壊れるため
|
public void onDayClick(Date date) { // Test
|
||||||
try {
|
List<Event> events = compactCalendarView.getEvents(date);
|
||||||
Thread.sleep(500);
|
|
||||||
} catch (InterruptedException e) {
|
ScrollView scrollView = new ScrollView(requireContext());
|
||||||
e.printStackTrace();
|
LinearLayout linearLayout = new LinearLayout(requireContext());
|
||||||
|
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
linearLayout.setPadding(96, 24, 96, 24);
|
||||||
|
scrollView.addView(linearLayout);
|
||||||
|
|
||||||
|
events.forEach(event -> {
|
||||||
|
TextView textView = new TextView(requireContext());
|
||||||
|
textView.setText(((HistoryModel) event.getData()).getTaskName() + " @ " + ((HistoryModel) event.getData()).getChildId());
|
||||||
|
textView.setPadding(0, 0, 0, 24);
|
||||||
|
linearLayout.addView(textView);
|
||||||
|
});
|
||||||
|
|
||||||
|
new MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle("タスク一覧 (DEBUG)")
|
||||||
|
.setMessage(events.size() + "件のタスクが登録されています")
|
||||||
|
.setView(scrollView)
|
||||||
|
.setNeutralButton("閉じる", (dialog, which) -> dialog.dismiss())
|
||||||
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMonthScroll(Date date) {
|
||||||
|
// 0000年00月の形式に変換 getYear/getMonthは非推奨
|
||||||
|
calendarTitleTextView.setText(String.format("%d年%d月", date.getYear() + 1900, date.getMonth() + 1)); // 統合
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初回
|
||||||
|
Date date = new Date();
|
||||||
|
calendarTitleTextView.setText(String.format("%d年%d月", date.getYear() + 1900, date.getMonth() + 1)); // 統合
|
||||||
|
|
||||||
|
calendarPrevButton.setOnClickListener(v -> {
|
||||||
|
compactCalendarView.scrollLeft();
|
||||||
|
});
|
||||||
|
|
||||||
|
calendarNextButton.setOnClickListener(v -> {
|
||||||
|
compactCalendarView.scrollRight();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* データを更新 (updateTaskInfoとupdateCalenderを並列実行)
|
||||||
|
*/
|
||||||
|
private void updateData() {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
swipeRefreshLayout.setRefreshing(true);
|
||||||
|
});
|
||||||
|
CompletableFuture.allOf(updateTaskInfo(), updateCalender()).thenRun(() -> {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
swipeRefreshLayout.setRefreshing(false);
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* タスク追加ダイアログを表示
|
||||||
|
*/
|
||||||
|
private void showAddTaskDialog() {
|
||||||
|
View view = getLayoutInflater().inflate(R.layout.common_task_add_dialog_layout, null);
|
||||||
|
view.setPadding(48, 24, 48, 24);
|
||||||
|
new MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle("タスクを追加")
|
||||||
|
.setView(view)
|
||||||
|
.setPositiveButton("追加", (dialog, which) -> {
|
||||||
|
EditText taskNameEditText = view.findViewById(R.id.addTaskNameEditText);
|
||||||
|
EditText taskRewardEditText = view.findViewById(R.id.addTaskRewardEditText);
|
||||||
|
TaskItemModel taskItemModel = new TaskItemModel();
|
||||||
|
taskItemModel.setName(taskNameEditText.getText().toString());
|
||||||
|
taskItemModel.setReward(Integer.parseInt(taskRewardEditText.getText().toString()));
|
||||||
|
taskData.addTask(taskItemModel).thenRun(this::updateData);
|
||||||
|
})
|
||||||
|
.setNegativeButton("キャンセル", (dialog, which) -> dialog.dismiss())
|
||||||
|
.show();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package one.nem.kidshift.feature.common;
|
||||||
|
|
||||||
|
import static androidx.navigation.Navigation.findNavController;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
import one.nem.kidshift.data.ChildData;
|
||||||
|
import one.nem.kidshift.feature.common.adapter.SelectShowChildListItemAdapter;
|
||||||
|
import one.nem.kidshift.utils.FabManager;
|
||||||
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.RecyclerViewAnimUtils;
|
||||||
|
import one.nem.kidshift.utils.ToolBarManager;
|
||||||
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
public class CommonSelectChildFragment extends Fragment {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
KSLoggerFactory loggerFactory;
|
||||||
|
@Inject
|
||||||
|
ChildData childData;
|
||||||
|
@Inject
|
||||||
|
FabManager fabManager;
|
||||||
|
@Inject
|
||||||
|
ToolBarManager toolBarManager;
|
||||||
|
@Inject
|
||||||
|
RecyclerViewAnimUtils recyclerViewAnimUtils;
|
||||||
|
private KSLogger logger;
|
||||||
|
|
||||||
|
private SelectShowChildListItemAdapter adapter;
|
||||||
|
|
||||||
|
public CommonSelectChildFragment() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
logger = loggerFactory.create("CommonSelectChildFragment");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
View view = inflater.inflate(R.layout.fragment_common_select_child, container, false);
|
||||||
|
|
||||||
|
RecyclerView childListRecyclerView = view.findViewById(R.id.selectShowChildListRecyclerView);
|
||||||
|
childListRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
recyclerViewAnimUtils.setSlideUpAnimation(childListRecyclerView);
|
||||||
|
adapter = new SelectShowChildListItemAdapter();
|
||||||
|
adapter.setCallback(childId -> {
|
||||||
|
// 静的解析エラーが発生するのになぜか実行はできる↓
|
||||||
|
findNavController(view).navigate(CommonSelectChildFragmentDirections.actionCommonSelectChildFragmentToCommonHomeFragmentParentChild(childId));
|
||||||
|
});
|
||||||
|
CompletableFuture.runAsync(() -> childListRecyclerView.setAdapter(adapter)).thenRun(() -> childData.getChildListDirect().thenAccept(childList -> {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
adapter.setChildDataList(childList);
|
||||||
|
adapter.notifyItemRangeChanged(0, childList.size());
|
||||||
|
});
|
||||||
|
}).exceptionally(e -> {
|
||||||
|
logger.error("Failed to load child list");
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
fabManager.hide();
|
||||||
|
toolBarManager.setTitle("子供選択");
|
||||||
|
toolBarManager.setSubtitle(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package one.nem.kidshift.feature.common.adapter;
|
package one.nem.kidshift.feature.common.adapter;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
@ -37,7 +38,7 @@ public class ChildListItemAdapter extends RecyclerView.Adapter<ChildListItemAdap
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ChildListItemAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ChildListItemAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
View view = View.inflate(parent.getContext(), R.layout.list_item_task_completion_child, null);
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_task_completion_child, parent, false);
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
package one.nem.kidshift.feature.common.adapter;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import one.nem.kidshift.feature.common.R;
|
||||||
|
import one.nem.kidshift.model.ChildModel;
|
||||||
|
|
||||||
|
public class SelectShowChildListItemAdapter extends RecyclerView.Adapter<SelectShowChildListItemAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
private List<ChildModel> childDataList;
|
||||||
|
private CompleteButtonClickedCallback callback;
|
||||||
|
|
||||||
|
public SelectShowChildListItemAdapter() {
|
||||||
|
// Empty constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectShowChildListItemAdapter(List<ChildModel> childDataList) {
|
||||||
|
this.childDataList = childDataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildDataList(List<ChildModel> childDataList) {
|
||||||
|
this.childDataList = childDataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallback(CompleteButtonClickedCallback callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public SelectShowChildListItemAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_select_show_child, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull SelectShowChildListItemAdapter.ViewHolder holder, int position) {
|
||||||
|
ChildModel childData = childDataList.get(position);
|
||||||
|
holder.childName.setText(childData.getName());
|
||||||
|
holder.selectButton.setOnClickListener(v -> {
|
||||||
|
if (callback != null) {
|
||||||
|
callback.onClicked(childData.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return childDataList == null ? 0 : childDataList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView childName;
|
||||||
|
Button selectButton;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull android.view.View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
childName = itemView.findViewById(R.id.childNameTextView);
|
||||||
|
selectButton = itemView.findViewById(R.id.selectButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CompleteButtonClickedCallback {
|
||||||
|
void onClicked(String taskId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?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="wrap_content"
|
||||||
|
android:layout_margin="0dp">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/addTaskNameTextInputLayout"
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="タスク名"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/addTaskNameEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/addTaskRewardTextInputLayout"
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:hint="金額"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/addTaskNameTextInputLayout">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/addTaskRewardEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="number" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -11,22 +11,72 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:id="@+id/calendarContainer">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/colorSurface">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/calendarPrevButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:src="@drawable/arrow_back_24px"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:tint="@color/colorOnSurface"
|
||||||
|
android:padding="8dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/calendarTitleTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/colorOnSurface"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:text="2000年1月"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/calendarNextButton"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/calendarPrevButton"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/calendarNextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:src="@drawable/arrow_forward_24px"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:tint="@color/colorOnSurface"
|
||||||
|
android:padding="8dp"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<com.github.sundeepk.compactcalendarview.CompactCalendarView
|
<com.github.sundeepk.compactcalendarview.CompactCalendarView
|
||||||
android:id="@+id/calendar"
|
android:id="@+id/calendar"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="250dp"
|
android:layout_height="300dp"
|
||||||
android:paddingLeft="10dp"
|
android:paddingLeft="10dp"
|
||||||
android:paddingRight="10dp"
|
android:paddingRight="10dp"
|
||||||
app:compactCalendarBackgroundColor="#ffe95451"
|
app:compactCalendarBackgroundColor="@color/colorSurface"
|
||||||
app:compactCalendarCurrentDayBackgroundColor="#B71C1C"
|
app:compactCalendarCurrentDayBackgroundColor="@color/colorSurfaceVariant"
|
||||||
app:compactCalendarCurrentSelectedDayBackgroundColor="#E57373"
|
app:compactCalendarCurrentSelectedDayBackgroundColor="@color/colorSurfaceVariant"
|
||||||
app:compactCalendarMultiEventIndicatorColor="#fff"
|
app:compactCalendarMultiEventIndicatorColor="@color/colorOnSurface"
|
||||||
app:compactCalendarTargetHeight="250dp"
|
app:compactCalendarTextColor="@color/colorOnSurface"
|
||||||
app:compactCalendarTextColor="#fff"
|
app:compactCalendarTextSize="12sp"/>
|
||||||
app:compactCalendarTextSize="12sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
</LinearLayout>
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/taskListRecyclerView"
|
android:id="@+id/taskListRecyclerView"
|
||||||
|
@ -35,7 +85,7 @@
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/calendar" />
|
app:layout_constraintTop_toBottomOf="@+id/calendarContainer" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?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=".CommonSelectChildFragment" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="128dp"
|
||||||
|
android:text="使用するお子様を選択"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/selectShowChildListRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:layout_marginBottom="128dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/textView2" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -4,7 +4,8 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="12dp">
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:layout_marginVertical="8dp">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/textContainer"
|
android:id="@+id/textContainer"
|
||||||
|
@ -16,7 +17,6 @@
|
||||||
android:id="@+id/task_title_text_view"
|
android:id="@+id/task_title_text_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:text="お手伝い名"
|
android:text="お手伝い名"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
|
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
|
@ -27,7 +27,6 @@
|
||||||
android:id="@+id/task_contents_text_view"
|
android:id="@+id/task_contents_text_view"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:layout_marginTop="13dp"
|
android:layout_marginTop="13dp"
|
||||||
android:text="円/回"
|
android:text="円/回"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?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="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:layout_marginVertical="4dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="8px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/childNameTextView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="PLACEHOLDER"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||||
|
|
||||||
|
<!-- ImageButtonに変更? -->
|
||||||
|
<Button
|
||||||
|
android:id="@+id/selectButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="表示" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -3,7 +3,9 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:layout_marginVertical="4dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -22,11 +24,12 @@
|
||||||
android:text="PLACEHOLDER"
|
android:text="PLACEHOLDER"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||||
|
|
||||||
|
<!-- ImageButtonに変更? -->
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/completeButton"
|
android:id="@+id/completeButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Button" />
|
android:text="完了" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/toggle_calendar"
|
||||||
|
android:icon="@drawable/calendar_month_24px"
|
||||||
|
app:showAsAction="ifRoom"
|
||||||
|
android:title="カレンダー表示切り替え" />
|
||||||
|
|
||||||
|
</menu>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?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_common_child_child_navigation"
|
||||||
|
app:startDestination="@id/commonHomeFragmentChildChild">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/commonHomeFragmentChildChild"
|
||||||
|
android:name="one.nem.kidshift.feature.common.CommonHomeFragment"
|
||||||
|
android:label="fragment_common_home"
|
||||||
|
tools:layout="@layout/fragment_common_home" >
|
||||||
|
<argument
|
||||||
|
android:name="childId"
|
||||||
|
app:argType="string" />
|
||||||
|
<argument
|
||||||
|
android:name="isChildMode"
|
||||||
|
app:argType="boolean"
|
||||||
|
android:defaultValue="true" />
|
||||||
|
</fragment>
|
||||||
|
</navigation>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?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_common_parent_child_navigation"
|
||||||
|
app:startDestination="@id/commonSelectChildFragment">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/commonHomeFragmentParentChild"
|
||||||
|
android:name="one.nem.kidshift.feature.common.CommonHomeFragment"
|
||||||
|
android:label="fragment_common_home"
|
||||||
|
tools:layout="@layout/fragment_common_home" />
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/commonSelectChildFragment"
|
||||||
|
android:name="one.nem.kidshift.feature.common.CommonSelectChildFragment"
|
||||||
|
android:label="fragment_common_select_child"
|
||||||
|
tools:layout="@layout/fragment_common_select_child" >
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_commonSelectChildFragment_to_commonHomeFragmentParentChild"
|
||||||
|
app:destination="@id/commonHomeFragmentParentChild" >
|
||||||
|
<argument
|
||||||
|
android:name="childId"
|
||||||
|
app:argType="string" />
|
||||||
|
<argument
|
||||||
|
android:name="isChildMode"
|
||||||
|
app:argType="boolean"
|
||||||
|
android:defaultValue="true" />
|
||||||
|
</action>
|
||||||
|
</fragment>
|
||||||
|
</navigation>
|
|
@ -2,11 +2,11 @@
|
||||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/feature_common_navigation"
|
android:id="@+id/feature_common_parent_parent_navigation"
|
||||||
app:startDestination="@id/commonHomeFragment">
|
app:startDestination="@id/commonHomeFragmentParentParent">
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/commonHomeFragment"
|
android:id="@+id/commonHomeFragmentParentParent"
|
||||||
android:name="one.nem.kidshift.feature.common.CommonHomeFragment"
|
android:name="one.nem.kidshift.feature.common.CommonHomeFragment"
|
||||||
android:label="fragment_common_home"
|
android:label="fragment_common_home"
|
||||||
tools:layout="@layout/fragment_common_home" />
|
tools:layout="@layout/fragment_common_home" />
|
|
@ -1,8 +0,0 @@
|
||||||
<?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_parent_navigation"
|
|
||||||
app:startDestination="@id/feature_common_navigation">
|
|
||||||
<include app:graph="@navigation/feature_common_navigation" />
|
|
||||||
</navigation>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<?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"
|
|
||||||
android:id="@+id/internal_parent_navigation">
|
|
||||||
|
|
||||||
<include app:graph="@navigation/feature_common_navigation" />
|
|
||||||
</navigation>
|
|
1
feature/wallet/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
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
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
|
@ -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,253 @@
|
||||||
|
package one.nem.kidshift.wallet;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
|
|
||||||
|
public class HistoryItemListAdapter extends RecyclerView.Adapter<HistoryItemListAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
enum ViewType {
|
||||||
|
WITH_HEADER(1),
|
||||||
|
ITEM(0);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
ViewType(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HistoryModelExtended extends HistoryModel {
|
||||||
|
private boolean isChecked;
|
||||||
|
|
||||||
|
public boolean isChecked() {
|
||||||
|
return isChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecked(boolean checked) {
|
||||||
|
isChecked = checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add isChecked to the constructor
|
||||||
|
public HistoryModelExtended() {
|
||||||
|
super();
|
||||||
|
isChecked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy constructor
|
||||||
|
public HistoryModelExtended(HistoryModel historyModel) {
|
||||||
|
super();
|
||||||
|
this.setId(historyModel.getId());
|
||||||
|
this.setPaid(historyModel.isPaid());
|
||||||
|
this.setChildId(historyModel.getChildId());
|
||||||
|
this.setRegisteredAt(historyModel.getRegisteredAt());
|
||||||
|
this.setTaskId(historyModel.getTaskId());
|
||||||
|
this.setTaskName(historyModel.getTaskName());
|
||||||
|
this.setReward(historyModel.getReward());
|
||||||
|
this.setChecked(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HistoryModelExtendedList {
|
||||||
|
private List<HistoryModelExtended> list;
|
||||||
|
|
||||||
|
public List<HistoryModelExtended> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List<HistoryModelExtended> list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear all checked items
|
||||||
|
public void clearChecked() {
|
||||||
|
for (HistoryModelExtended item : list) {
|
||||||
|
item.setChecked(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public HistoryModelExtendedList() {
|
||||||
|
list = new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CheckBoxChangedCallback {
|
||||||
|
void onCheckBoxChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasChecked() {
|
||||||
|
for (HistoryModelExtended historyModelExtended : historyDataList.getList()) {
|
||||||
|
if (historyModelExtended.isChecked()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HistoryModelExtendedList historyDataList;
|
||||||
|
private CheckBoxChangedCallback callback;
|
||||||
|
private boolean hideCheckBox; // for child mode
|
||||||
|
|
||||||
|
public void setHistoryDataList(List<HistoryModel> historyDataList) {
|
||||||
|
this.historyDataList = new HistoryModelExtendedList();
|
||||||
|
for (HistoryModel historyModel : historyDataList) {
|
||||||
|
this.historyDataList.getList().add(new HistoryModelExtended(historyModel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallback(CheckBoxChangedCallback callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHideCheckBox(boolean hideCheckBox) {
|
||||||
|
this.hideCheckBox = hideCheckBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HistoryModel> getCheckedHistoryDataList() {
|
||||||
|
List<HistoryModel> checkedHistoryDataList = new ArrayList<>();
|
||||||
|
for (HistoryModelExtended historyModelExtended : historyDataList.getList()) {
|
||||||
|
if (historyModelExtended.isChecked()) {
|
||||||
|
checkedHistoryDataList.add(historyModelExtended);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkedHistoryDataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
if (position == 0) {
|
||||||
|
return ViewType.WITH_HEADER.getValue();
|
||||||
|
} else {
|
||||||
|
if (isFirstOfMonth(historyDataList.getList().get(position))) {
|
||||||
|
return ViewType.WITH_HEADER.getValue();
|
||||||
|
} else {
|
||||||
|
return ViewType.ITEM.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public HistoryItemListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
if (viewType == ViewType.WITH_HEADER.getValue()) {
|
||||||
|
LinearLayout view = new LinearLayout(parent.getContext());
|
||||||
|
|
||||||
|
view.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
view.addView(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_history_month_header, parent, false));
|
||||||
|
view.addView(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_history_list_item, parent, false));
|
||||||
|
return new MonthHeaderViewHolder(view);
|
||||||
|
} else {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_history_list_item, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull HistoryItemListAdapter.ViewHolder holder, int position) {
|
||||||
|
HistoryModelExtended historyData = this.historyDataList.getList().get(position);
|
||||||
|
if (historyData.isPaid() || hideCheckBox) {
|
||||||
|
holder.historyItemCheckBox.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
holder.historyItemCheckBox.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
holder.historyItemNameTextView.setText(historyData.getTaskName());
|
||||||
|
holder.historyItemRewardTextView.setText(historyData.getReward() + "円");
|
||||||
|
holder.historyItemCheckBox.setChecked(historyData.isChecked());
|
||||||
|
holder.historyItemCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
|
if (holder.historyItemCheckBox.isShown()) {
|
||||||
|
historyData.setChecked(isChecked);
|
||||||
|
callback.onCheckBoxChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (holder instanceof MonthHeaderViewHolder) {
|
||||||
|
((MonthHeaderViewHolder) holder).monthHeaderTitle.setText(historyData.getRegisteredAt().getMonth() + 1 + "月");
|
||||||
|
// // DEBUG: 月をまたぐデータがないので
|
||||||
|
// ((MonthHeaderViewHolder) holder).monthHeaderTitle.setText(historyData.getRegisteredAt().getDate() + "日");
|
||||||
|
((MonthHeaderViewHolder) holder).monthTotalTextView.setText(getMonthTotal(historyData) + "円");
|
||||||
|
((MonthHeaderViewHolder) holder).checkAllButton.setOnClickListener(v -> {
|
||||||
|
Toast.makeText(v.getContext(), "実装中", Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFirstOfMonth(HistoryModel historyModel) {
|
||||||
|
// 1個前の要素と比較して月が変わったかどうかを判定する
|
||||||
|
if (historyDataList.getList().indexOf(historyModel) == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
HistoryModel previousHistoryModel = historyDataList.getList().get(historyDataList.getList().indexOf(historyModel) - 1);
|
||||||
|
// getMonth()はDeprecated TODO: やめる
|
||||||
|
return historyModel.getRegisteredAt().getMonth() != previousHistoryModel.getRegisteredAt().getMonth();
|
||||||
|
// DEBUG: 月をまたぐデータがないので
|
||||||
|
// return historyModel.getRegisteredAt().getDate() != previousHistoryModel.getRegisteredAt().getDate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMonthTotal(HistoryModel historyModel) {
|
||||||
|
int total = historyModel.getReward();
|
||||||
|
int index = historyDataList.getList().indexOf(historyModel) + 1;
|
||||||
|
try {
|
||||||
|
while (!isFirstOfMonth(this.historyDataList.getList().get(index))) {
|
||||||
|
total += historyModel.getReward();
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
// 1個しかない場合 Workaround
|
||||||
|
// TODO: 例外をひねり潰すのではなく,そもそも発生しないようにするべき
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return historyDataList == null ? 0 : historyDataList.getList().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView historyItemNameTextView;
|
||||||
|
TextView historyItemRewardTextView;
|
||||||
|
CheckBox historyItemCheckBox;
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
historyItemNameTextView = itemView.findViewById(R.id.historyItemNameTextView);
|
||||||
|
historyItemRewardTextView = itemView.findViewById(R.id.historyItemRewardTextView);
|
||||||
|
historyItemCheckBox = itemView.findViewById(R.id.checkBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MonthHeaderViewHolder extends HistoryItemListAdapter.ViewHolder {
|
||||||
|
// かなり邪道な方法だけど,とりあえず取得できるので
|
||||||
|
|
||||||
|
TextView monthHeaderTitle;
|
||||||
|
TextView monthTotalTextView;
|
||||||
|
ImageButton checkAllButton;
|
||||||
|
|
||||||
|
public MonthHeaderViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
monthHeaderTitle = itemView.findViewById(R.id.monthHeaderTitle);
|
||||||
|
monthTotalTextView = itemView.findViewById(R.id.monthTotalTextView);
|
||||||
|
checkAllButton = itemView.findViewById(R.id.checkAllButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
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.data.UserSettings;
|
||||||
|
import one.nem.kidshift.model.HistoryModel;
|
||||||
|
import one.nem.kidshift.utils.FabManager;
|
||||||
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.RecyclerViewAnimUtils;
|
||||||
|
import one.nem.kidshift.utils.ToolBarManager;
|
||||||
|
import one.nem.kidshift.utils.factory.KSLoggerFactory;
|
||||||
|
import one.nem.kidshift.utils.models.FabEventCallback;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
public class WalletContentFragment extends Fragment {
|
||||||
|
|
||||||
|
private static final String ARG_CHILD_ID = "childId";
|
||||||
|
@Inject
|
||||||
|
KSLoggerFactory loggerFactory;
|
||||||
|
@Inject
|
||||||
|
RewardData rewardData;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
FabManager fabManager;
|
||||||
|
@Inject
|
||||||
|
ToolBarManager toolBarManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
UserSettings userSettings;
|
||||||
|
@Inject
|
||||||
|
RecyclerViewAnimUtils recyclerViewAnimUtils;
|
||||||
|
|
||||||
|
private KSLogger logger;
|
||||||
|
private String childId;
|
||||||
|
|
||||||
|
private TextView totalRewardTextView;
|
||||||
|
private SwipeRefreshLayout swipeRefreshLayout;
|
||||||
|
|
||||||
|
private HistoryItemListAdapter historyItemListAdapter;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WalletContentFragment newInstance() {
|
||||||
|
return new WalletContentFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
if (childId == null) {
|
||||||
|
// 単品で呼び出されてる = 子供モードでログインされている
|
||||||
|
childId = userSettings.getAppCommonSetting().getChildId();
|
||||||
|
if (childId == null) {
|
||||||
|
logger.error("Child ID is not set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
|
||||||
|
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout);
|
||||||
|
|
||||||
|
swipeRefreshLayout.setOnRefreshListener(() -> {
|
||||||
|
// updateTotalReward();
|
||||||
|
updateItems();
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
RecyclerView historyItemRecyclerView = view.findViewById(R.id.historyItemRecyclerView);
|
||||||
|
recyclerViewAnimUtils.setSlideUpAnimation(historyItemRecyclerView);
|
||||||
|
historyItemListAdapter = new HistoryItemListAdapter();
|
||||||
|
historyItemRecyclerView.setAdapter(historyItemListAdapter);
|
||||||
|
historyItemRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||||
|
|
||||||
|
historyItemListAdapter.setHideCheckBox(userSettings.getAppCommonSetting().isChildMode());
|
||||||
|
|
||||||
|
historyItemListAdapter.setCallback(() -> {
|
||||||
|
if (historyItemListAdapter.hasChecked()) {
|
||||||
|
fabManager.show();
|
||||||
|
initFab();
|
||||||
|
} else {
|
||||||
|
fabManager.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initFab() {
|
||||||
|
fabManager.setFabEventCallback(new FabEventCallback() {
|
||||||
|
@Override
|
||||||
|
public void onClicked() {
|
||||||
|
historyItemListAdapter.getCheckedHistoryDataList().forEach(historyModel -> {
|
||||||
|
rewardData.payReward(historyModel.getId()).thenRun(() -> {
|
||||||
|
logger.debug("Paid reward: " + historyModel.getId());
|
||||||
|
updateItems();
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
logger.error("Failed to pay reward: " + throwable.getMessage());
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
updateItems(); // workaround
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLongClicked() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
updateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateItems() {
|
||||||
|
swipeRefreshLayout.setRefreshing(true);
|
||||||
|
rewardData.getRewardHistoryList(childId).thenAccept(historyList -> {
|
||||||
|
historyItemListAdapter.setHistoryDataList(historyList);
|
||||||
|
// totalRewardTextView.setText(String.valueOf(historyList.stream().mapToInt(HistoryModel::getReward).sum()) + "円");
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
historyItemListAdapter.notifyDataSetChanged();
|
||||||
|
totalRewardTextView.setText(String.valueOf(historyList.stream().filter(item -> !item.isPaid()).mapToInt(HistoryModel::getReward).sum()) + "円");
|
||||||
|
});
|
||||||
|
}).thenRun(() -> {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
});
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
logger.error("Failed to get history list: " + throwable.getMessage());
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTotalReward() {
|
||||||
|
swipeRefreshLayout.setRefreshing(true);
|
||||||
|
rewardData.getTotalReward(childId).thenAccept(totalReward -> {
|
||||||
|
logger.debug("Total reward: " + totalReward);
|
||||||
|
totalRewardTextView.setText(String.valueOf(totalReward) + "円");
|
||||||
|
}).thenRun(() -> {
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
});
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
logger.error("Failed to get total reward: " + throwable.getMessage());
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
rewardData.getRewardHistoryList(childId).thenAccept(historyList -> { // test
|
||||||
|
historyItemListAdapter.setHistoryDataList(historyList);
|
||||||
|
historyItemListAdapter.notifyDataSetChanged();
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
logger.error("Failed to get history list: " + throwable.getMessage());
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
// updateTotalReward();
|
||||||
|
// updateItems();
|
||||||
|
// fabManager.hide();
|
||||||
|
toolBarManager.setTitle("ウォレット");
|
||||||
|
toolBarManager.setSubtitle(null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
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.model.callback.ChildModelCallback;
|
||||||
|
import one.nem.kidshift.utils.FabManager;
|
||||||
|
import one.nem.kidshift.utils.KSLogger;
|
||||||
|
import one.nem.kidshift.utils.ToolBarManager;
|
||||||
|
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;
|
||||||
|
@Inject
|
||||||
|
FabManager fabManager;
|
||||||
|
@Inject
|
||||||
|
ToolBarManager toolBarManager;
|
||||||
|
|
||||||
|
private TabLayout tabLayout;
|
||||||
|
private ViewPager2 viewPager;
|
||||||
|
private TabAdapter tabAdapter;
|
||||||
|
|
||||||
|
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 = new TabAdapter(requireActivity());
|
||||||
|
|
||||||
|
viewPager.setAdapter(tabAdapter);
|
||||||
|
|
||||||
|
setupViewPager();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupViewPager() {
|
||||||
|
|
||||||
|
// デバッグ用
|
||||||
|
childData.getChildList(new ChildModelCallback() {
|
||||||
|
@Override
|
||||||
|
public void onUnchanged() {
|
||||||
|
// TODO: impl
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdated(List<ChildModel> childModelList) {
|
||||||
|
// TODO: impl
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed(String message) {
|
||||||
|
// TODO: impl
|
||||||
|
}
|
||||||
|
}).thenAccept(childModels -> {
|
||||||
|
|
||||||
|
// childData.getChildListDirect().thenAccept(childModels -> {
|
||||||
|
|
||||||
|
tabAdapter.setChildList(childModels);
|
||||||
|
requireActivity().runOnUiThread(() -> {
|
||||||
|
|
||||||
|
tabAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
|
||||||
|
tab.setText(childModels.get(position).getName());
|
||||||
|
}).attach();
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
fabManager.hide();
|
||||||
|
toolBarManager.setTitle("ウォレット");
|
||||||
|
toolBarManager.setSubtitle(null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?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:background="@color/colorSurface"
|
||||||
|
android:backgroundTintMode="add"
|
||||||
|
android:elevation="16px"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/historyItemRecyclerView"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
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:textColor="@color/colorOnSurface"
|
||||||
|
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"
|
||||||
|
android:textColor="@color/colorOnSurface" />
|
||||||
|
</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>
|