ft/adds app icon and rf navigation
@ -4,6 +4,7 @@
|
||||
<application
|
||||
android:label="app"
|
||||
android:name="${applicationName}"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
@ -28,6 +29,7 @@
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
|
BIN
frontend/app/android/app/src/main/res/ic_launcher-web.png
Normal file
After Width: | Height: | Size: 17 KiB |
@ -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="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
@ -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="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 11 KiB |
BIN
frontend/app/android/app/src/main/res/playstore-icon.png
Normal file
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#040404</color>
|
||||
</resources>
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 182 KiB |
BIN
frontend/app/assets/icon.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
107
frontend/app/assets/icon.svg
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 3072000 2048000"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="vector-SVG.svg"
|
||||
width="3072000"
|
||||
height="2048000"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs20" /><sodipodi:namedview
|
||||
id="namedview20"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1" /> <style
|
||||
type="text/css"
|
||||
id="style1"> .st0{fill:#FFFFFF;} </style> <rect
|
||||
x="-2963012"
|
||||
y="-975512"
|
||||
width="1024"
|
||||
height="1024"
|
||||
id="rect1"
|
||||
style="stroke-width:0.418046" /> <g
|
||||
id="g20"
|
||||
transform="translate(-2964000.1,-975619.87)"> <g
|
||||
id="g19"
|
||||
transform="matrix(0.57036525,0,0,0.57036525,644.47575,266.3177)"
|
||||
inkscape:export-filename="icon.png"
|
||||
inkscape:export-xdpi="32.768002"
|
||||
inkscape:export-ydpi="32.768002"> <g
|
||||
id="g4"> <g
|
||||
id="g1"> <path
|
||||
class="st0"
|
||||
d="m 1643.8,246.59 -62.38,104.92 57.67,47.96 46.96,-78.8 h 471.2 l 44.11,-74.08 z"
|
||||
id="path1" /> </g> <g
|
||||
id="g3"> <g
|
||||
id="g2"> <polygon
|
||||
class="st0"
|
||||
points="1507.63,473.84 1323.2,320.82 929.22,320.82 1212,795.3 1168.89,867.68 798.75,246.59 1350.04,246.59 1604.26,457.85 1568.29,518.38 2039.49,518.38 1995.24,592.61 1524.04,592.61 1285.51,993.15 1199.15,993.15 1507.91,474.13 "
|
||||
id="polygon1" /> </g> </g> </g> <g
|
||||
id="g18"
|
||||
style="display:none"> <g
|
||||
id="g17"> <g
|
||||
id="g16"> <path
|
||||
class="st0"
|
||||
d="m 462.6,1250.09 h -89.07 v 220.83 h 89.07 c 72.8,0 126.61,-42.97 126.61,-110.63 0,-67.38 -53.81,-110.2 -126.61,-110.2 z m 0,196.13 h -60.38 v -171.58 h 60.38 c 58.81,0 97.07,34.12 97.07,85.65 0,51.82 -38.26,85.93 -97.07,85.93 z"
|
||||
id="path4" /> <path
|
||||
class="st0"
|
||||
d="m 701.13,1250.09 v 220.83 h 28.55 v -220.83 z"
|
||||
id="path5" /> <path
|
||||
class="st0"
|
||||
d="M 1092.68,1354.01 H 967.63 v 23.84 l 94.64,0.43 c -2.28,10.56 -6,20.13 -11.13,29.26 -3,5.57 -7.28,10.56 -11.7,15.27 l -0.57,0.57 c -15.27,14.85 -36.54,24.55 -62.24,26.55 -3,0.43 -6.28,0.43 -9.56,0.43 h -3.71 c -35.83,-1.14 -64.38,-16.99 -79.65,-42.25 h -0.43 c -7.85,-13.56 -12.56,-29.55 -12.56,-47.82 0,-52.82 39.54,-89.64 96.35,-89.64 37.83,0 68.38,15.99 84.08,42.82 l 32.12,-0.43 c -18.56,-41.11 -62.09,-67.09 -116.19,-67.09 -72.37,0 -125.9,46.96 -125.9,114.34 0,66.8 51.82,113.63 122.91,114.62 h 9.56 c 3.71,-0.28 7.71,-0.71 11.42,-0.71 l 6.28,-1 c 11.85,-2 23.55,-5.28 33.55,-9.56 13.27,-5.71 25.12,-13.28 34.83,-22.55 0.29,-0.43 0.71,-0.71 0.71,-1.14 4.85,-4.71 9.56,-9.85 13.27,-15.56 l 0.86,-1 c 11.42,-16.56 17.7,-36.11 18.7,-58.1 -0.02,-6.57 -0.45,-8.57 -0.59,-11.28 z"
|
||||
id="path6" /> <path
|
||||
class="st0"
|
||||
d="m 1201.16,1250.09 v 220.83 h 28.41 v -220.83 z"
|
||||
id="path7" /> <path
|
||||
class="st0"
|
||||
d="m 1329.49,1250.09 v 24.27 h 83.65 v 196.56 h 28.55 v -196.56 h 84.08 v -24.27 z"
|
||||
id="path8" /> <path
|
||||
class="st0"
|
||||
d="m 1704.2,1250.09 h -32.97 l -101.21,220.83 h 31.83 l 25.98,-55.53 h 120.76 l 25.27,55.53 h 31.55 z m -65.09,141.46 48.82,-112.91 49.82,112.91 z"
|
||||
id="path9" /> <path
|
||||
class="st0"
|
||||
d="m 1934.3,1446.65 v -196.56 h -28.41 v 220.83 h 158.31 v -24.27 z"
|
||||
id="path10" /> <path
|
||||
class="st0"
|
||||
d="m 2193.24,1446.65 v -75.37 H 2313 v -23.98 h -119.76 v -72.94 h 139.18 v -24.27 h -167.73 v 220.83 h 170.72 v -24.27 z"
|
||||
id="path11" /> <path
|
||||
class="st0"
|
||||
d="m 2547.39,1368.28 h 3 c 45.82,0 73.8,-25.27 73.8,-59.52 0,-34.4 -27.98,-58.38 -73.8,-58.38 h -108.63 v 220.83 h 28.26 l 0.29,-102.92 h 44.11 l 75.51,102.63 h 36.54 z m -77.08,-24.69 v -69.23 h 80.08 c 28.55,0 44.11,12.42 44.11,34.12 0,21.27 -15.56,35.12 -44.11,35.12 h -80.08 z"
|
||||
id="path12" /> <g
|
||||
id="g15"> <polygon
|
||||
class="st0"
|
||||
points="911.43,1635.82 911.43,1622.14 817.17,1622.14 817.17,1753.32 831.98,1753.32 831.98,1696.16 903.01,1696.16 903.01,1682.67 831.98,1682.67 831.98,1635.82 "
|
||||
id="polygon12" /> <path
|
||||
class="st0"
|
||||
d="m 1097.67,1699.74 c 20.56,-3.85 35.54,-16.56 35.54,-38.4 0,-23.7 -18.7,-39.11 -47.39,-39.11 h -56.39 v 131.18 h 14.7 v -50.96 h 37.54 l 37.97,50.96 h 18.27 z m -53.53,-10.71 v -53.24 h 40.54 c 21.13,0 33.55,9.85 33.55,25.98 0,17.13 -14.13,27.26 -33.69,27.26 z"
|
||||
id="path13" /> <rect
|
||||
x="1257.67"
|
||||
y="1622.14"
|
||||
class="st0"
|
||||
width="14.81"
|
||||
height="131.17999"
|
||||
id="rect13" /> <polygon
|
||||
class="st0"
|
||||
points="1402.93,1622.14 1402.93,1753.32 1498.7,1753.32 1498.7,1739.83 1417.74,1739.83 1417.74,1693.91 1489.32,1693.91 1489.32,1680.42 1417.74,1680.42 1417.74,1635.63 1497.76,1635.63 1497.76,1622.14 "
|
||||
id="polygon13" /> <path
|
||||
class="st0"
|
||||
d="m 1663.8,1622.23 h -45.54 v 131.18 h 45.54 c 41.11,0 69.66,-28.83 69.66,-65.81 0,-37.11 -28.55,-65.37 -69.66,-65.37 z m 0,117.33 h -30.83 v -103.78 h 30.83 c 33.12,0 54.24,22.98 54.24,52.1 0,29.27 -21.12,51.68 -54.24,51.68 z"
|
||||
id="path14" /> <polygon
|
||||
class="st0"
|
||||
points="1856.72,1622.14 1856.72,1753.32 1952.47,1753.32 1952.47,1739.83 1871.52,1739.83 1871.52,1693.91 1943.11,1693.91 1943.11,1680.42 1871.52,1680.42 1871.52,1635.63 1951.54,1635.63 1951.54,1622.14 "
|
||||
id="polygon14" /> <polygon
|
||||
class="st0"
|
||||
points="2171.22,1753.32 2183.04,1753.32 2183.04,1622.14 2168.59,1622.14 2168.59,1727.27 2085.95,1622.14 2072.09,1622.14 2072.09,1753.32 2086.52,1753.32 2086.52,1645.76 "
|
||||
id="polygon15" /> </g> </g> </g> </g> </g> </g> </svg>
|
After Width: | Height: | Size: 5.9 KiB |
BIN
frontend/app/assets/icon_round.png
Normal file
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 420 B |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 508 B |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 737 B |
After Width: | Height: | Size: 793 B |
After Width: | Height: | Size: 1000 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
@ -1,122 +1,128 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"scale" : "1x"
|
||||
"images":[
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"20x20",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-20x20@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"20x20",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-20x20@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"29x29",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-29x29@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"29x29",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-29x29@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"29x29",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-29x29@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"40x40",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-40x40@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"40x40",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-40x40@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"60x60",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-60x60@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"60x60",
|
||||
"scale":"3x",
|
||||
"filename":"Icon-App-60x60@3x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"iphone",
|
||||
"size":"76x76",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-76x76@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"20x20",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-20x20@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"20x20",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-20x20@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"29x29",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-29x29@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"29x29",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-29x29@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"40x40",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-40x40@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"40x40",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-40x40@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"76x76",
|
||||
"scale":"1x",
|
||||
"filename":"Icon-App-76x76@1x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"76x76",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-76x76@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom":"ipad",
|
||||
"size":"83.5x83.5",
|
||||
"scale":"2x",
|
||||
"filename":"Icon-App-83.5x83.5@2x.png"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"filename" : "ItunesArtwork@2x.png"
|
||||
}
|
||||
],
|
||||
"info":{
|
||||
"version":1,
|
||||
"author":"easyappicon"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 950 B |
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 687 B |
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 950 B |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 39 KiB |
BIN
frontend/app/ios/Runner/Assets.xcassets/iTunesArtwork@1x.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
frontend/app/ios/Runner/Assets.xcassets/iTunesArtwork@2x.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
frontend/app/ios/Runner/Assets.xcassets/iTunesArtwork@3x.png
Normal file
After Width: | Height: | Size: 67 KiB |
@ -1,6 +1,12 @@
|
||||
import 'package:app/model/services/auth_service.dart';
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/pages/registration_page.dart';
|
||||
import 'package:app/pages/security_page.dart';
|
||||
import 'package:app/pages/start_page.dart';
|
||||
import 'package:app/pages/verify_email_page.dart';
|
||||
import 'package:app/pb/account.pb.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart'
|
||||
@ -63,8 +69,12 @@ class DigitalerFrieden extends StatefulWidget {
|
||||
|
||||
class _DigitalerFriedenState extends State<DigitalerFrieden> {
|
||||
final StorageService _storageService = StorageService();
|
||||
final BaseViewModel _vm = BaseViewModel();
|
||||
int? accountLevel;
|
||||
bool? authenticated;
|
||||
String? accessToken;
|
||||
bool authenticated = false;
|
||||
Account? account;
|
||||
bool verified = false;
|
||||
bool _loading = true;
|
||||
@override
|
||||
void initState() {
|
||||
@ -74,14 +84,29 @@ class _DigitalerFriedenState extends State<DigitalerFrieden> {
|
||||
|
||||
void _init() async {
|
||||
accountLevel = await _storageService.accountLevel;
|
||||
if (accountLevel! > 0) {
|
||||
accessToken = await _storageService.accessToken;
|
||||
verified = await _storageService.verified;
|
||||
if (accountLevel! > 1) {
|
||||
authenticated = await AuthService.authenticateWithBiometrics();
|
||||
}
|
||||
if (authenticated && accountLevel != null && accountLevel! > 3) {
|
||||
account = await _vm.account;
|
||||
}
|
||||
|
||||
if (account != null && !verified && account!.emailVerified) {
|
||||
await _storageService.setVerified(account!.emailVerified);
|
||||
verified = account!.emailVerified;
|
||||
}
|
||||
|
||||
print(
|
||||
'ACCOUNTLEVEL: $accountLevel ======= VERIFIED: $verified ======= ID: ${account?.id}\nTOKEN: $accessToken');
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getAccount(BuildContext context) async {}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_loading) {
|
||||
@ -107,6 +132,28 @@ class _DigitalerFriedenState extends State<DigitalerFrieden> {
|
||||
),
|
||||
);
|
||||
}
|
||||
return const StartPage();
|
||||
if (verified) {
|
||||
switch (accountLevel) {
|
||||
default:
|
||||
return const StartPage();
|
||||
}
|
||||
} else {
|
||||
switch (accountLevel) {
|
||||
case 1:
|
||||
return const SecurityPage();
|
||||
case 2:
|
||||
return const NotificationsPage();
|
||||
case 4:
|
||||
return const VerifyEmailPage();
|
||||
case 3:
|
||||
if (accessToken != null) {
|
||||
return const VerifyEmailPage();
|
||||
} else {
|
||||
return const RegistrationPage();
|
||||
}
|
||||
default:
|
||||
return const StartPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,13 +126,13 @@ class BackendService {
|
||||
Future<bool> createAccount(
|
||||
{required String email, required String password}) async {
|
||||
try {
|
||||
final resp =
|
||||
await BackendService.client.createAccount(CreateAccountRequest(
|
||||
// final resp =
|
||||
await BackendService.client.createAccount(CreateAccountRequest(
|
||||
email: email,
|
||||
password: password,
|
||||
));
|
||||
print(resp);
|
||||
await _storageService.setAccountId(resp.account.id);
|
||||
// print(resp);
|
||||
// await _storageService.setAccountId(resp.account.id);
|
||||
return await login(email: email, password: password);
|
||||
} on SocketException {
|
||||
throw FetchDataException('Keine Internet Verbindung');
|
||||
@ -162,6 +162,29 @@ class BackendService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Account?> get account async {
|
||||
try {
|
||||
final id = await _storageService.accountId;
|
||||
if (id == 0) {
|
||||
return null;
|
||||
}
|
||||
final resp = await _client.getAccount(GetAccountRequest(id: id),
|
||||
options: CallOptions(metadata: {
|
||||
'Authorization': 'Bearer ${await _storageService.accessToken}'
|
||||
}));
|
||||
if (resp.account.id < 1) {
|
||||
return null;
|
||||
}
|
||||
return resp.account;
|
||||
} on SocketException {
|
||||
throw FetchDataException('Keine Internet Verbindung');
|
||||
} on GrpcError catch (err) {
|
||||
throw FetchDataException('${err.message}');
|
||||
} catch (err) {
|
||||
throw InternalException(err.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<Account> getAccount() async {
|
||||
Session? session = await _isLoggedIn();
|
||||
if (session == null) {
|
||||
@ -399,6 +422,7 @@ class BackendService {
|
||||
// );
|
||||
|
||||
await _storageService.setAccessToken(response.accessToken);
|
||||
await _storageService.setAccountId(response.accountId);
|
||||
|
||||
// await Session.newSession(s);
|
||||
return response.accessToken != '';
|
||||
|
@ -73,6 +73,14 @@ class StorageService {
|
||||
return await readData('access_token');
|
||||
}
|
||||
|
||||
Future<void> setVerified(bool verified) async {
|
||||
return await writeData(StorageItem('verified', verified ? '1' : '0'));
|
||||
}
|
||||
|
||||
Future<bool> get verified async {
|
||||
return await readData('verified') == '1';
|
||||
}
|
||||
|
||||
Future<void> setAccountId(Int64 accountId) async {
|
||||
return await writeData(StorageItem('account_id', '$accountId'));
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
import 'package:app/model/apis/api_response.dart';
|
||||
import 'package:app/model/services/backend_service.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pb/account.pb.dart';
|
||||
|
||||
class AccountViewModel extends BaseViewModel {
|
||||
AccountViewModel() {
|
||||
_init();
|
||||
}
|
||||
final ApiResponse _apiResponse = ApiResponse.initial('Keine Daten');
|
||||
|
||||
final BackendService _service = BackendService();
|
||||
Account? _account;
|
||||
|
||||
@override
|
||||
ApiResponse get response {
|
||||
return _apiResponse;
|
||||
}
|
||||
|
||||
Account? get account {
|
||||
return _account;
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
// super.init();
|
||||
// try {
|
||||
// _apiResponse = ApiResponse.completed(await _service.getAccount());
|
||||
// } catch (e) {
|
||||
// _apiResponse = ApiResponse.error(e.toString());
|
||||
// }
|
||||
// notifyListeners();
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import 'package:app/model/apis/api_response.dart';
|
||||
import 'package:app/model/services/backend_service.dart';
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages_draft/home_page.dart';
|
||||
import 'package:app/pb/account.pb.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -29,51 +29,59 @@ class BaseViewModel with ChangeNotifier {
|
||||
// // }
|
||||
// }
|
||||
|
||||
Future<bool> isLoggedIn(BuildContext context) async {
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
final navigator = Navigator.of(context);
|
||||
bool loggedIn = false;
|
||||
try {
|
||||
loggedIn = await BackendService.isLoggedIn;
|
||||
} catch (err) {
|
||||
if (err.toString().contains('session is blocked')) {
|
||||
_apiResponse = ApiResponse.error('Sitzung ist abgelaufen');
|
||||
navigator.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => HomePage(
|
||||
loggedOut: true,
|
||||
)),
|
||||
(route) => false);
|
||||
messenger.showSnackBar(SnackBar(
|
||||
backgroundColor: CustomColors.error,
|
||||
content: const Text(
|
||||
'Sitzung ist abgelaufen',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
// action: SnackBarAction(
|
||||
// label: 'Details',
|
||||
// onPressed: () {
|
||||
// if (context.mounted) {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) => AlertDialog(
|
||||
// backgroundColor: Colors.black,
|
||||
// icon: Icon(
|
||||
// Icons.error,
|
||||
// color: CustomColors.error,
|
||||
// ),
|
||||
// content: Text(
|
||||
// err.toString(),
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
// ));
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
));
|
||||
}
|
||||
}
|
||||
return loggedIn;
|
||||
// Future<bool> isLoggedIn(BuildContext context) async {
|
||||
// final messenger = ScaffoldMessenger.of(context);
|
||||
// final navigator = Navigator.of(context);
|
||||
// bool loggedIn = false;
|
||||
// try {
|
||||
// loggedIn = await BackendService.isLoggedIn;
|
||||
// } catch (err) {
|
||||
// if (err.toString().contains('session is blocked')) {
|
||||
// _apiResponse = ApiResponse.error('Sitzung ist abgelaufen');
|
||||
// navigator.pushAndRemoveUntil(
|
||||
// MaterialPageRoute(
|
||||
// builder: (builder) => HomePage(
|
||||
// loggedOut: true,
|
||||
// )),
|
||||
// (route) => false);
|
||||
// messenger.showSnackBar(SnackBar(
|
||||
// backgroundColor: CustomColors.error,
|
||||
// content: const Text(
|
||||
// 'Sitzung ist abgelaufen',
|
||||
// style: TextStyle(color: Colors.white),
|
||||
// ),
|
||||
// // action: SnackBarAction(
|
||||
// // label: 'Details',
|
||||
// // onPressed: () {
|
||||
// // if (context.mounted) {
|
||||
// // showDialog(
|
||||
// // context: context,
|
||||
// // builder: (context) => AlertDialog(
|
||||
// // backgroundColor: Colors.black,
|
||||
// // icon: Icon(
|
||||
// // Icons.error,
|
||||
// // color: CustomColors.error,
|
||||
// // ),
|
||||
// // content: Text(
|
||||
// // err.toString(),
|
||||
// // textAlign: TextAlign.center,
|
||||
// // ),
|
||||
// // ));
|
||||
// // }
|
||||
// // },
|
||||
// // ),
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
// return loggedIn;
|
||||
// }
|
||||
|
||||
Future<Account?> get account async {
|
||||
notifyListeners();
|
||||
final acc = await _service.account;
|
||||
ApiResponse.completed(acc);
|
||||
notifyListeners();
|
||||
return acc;
|
||||
}
|
||||
|
||||
Future<void> getAccount(BuildContext context) async {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/registration_page.dart';
|
||||
import 'package:app/pages/security_page.dart';
|
||||
import 'package:app/pages/verify_email_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -25,18 +27,12 @@ class _NotificationsPageState extends State<NotificationsPage> {
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
final accountLevel = await _storageService.accountLevel;
|
||||
if (accountLevel > 2 && mounted) {
|
||||
await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (builder) => const RegistrationPage()));
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
if (await _storageService.accountLevel < 2) {
|
||||
await _storageService.setAccountLevel(2);
|
||||
}
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -67,11 +63,12 @@ class _NotificationsPageState extends State<NotificationsPage> {
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () async {
|
||||
await _storageService.setAccountLevel(1);
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const SecurityPage()),
|
||||
(route) => false);
|
||||
},
|
||||
),
|
||||
iconTheme: IconThemeData(
|
||||
@ -125,15 +122,25 @@ class _NotificationsPageState extends State<NotificationsPage> {
|
||||
),
|
||||
onPressed: () async {
|
||||
await _setNotificationSetting(true);
|
||||
await _storageService.setAccountLevel(3);
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const RegistrationPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
if (await _storageService.accessToken != null) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const VerifyEmailPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const RegistrationPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
@ -163,15 +170,26 @@ class _NotificationsPageState extends State<NotificationsPage> {
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await _setNotificationSetting(false);
|
||||
await _storageService.setAccountLevel(3);
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const RegistrationPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
if (await _storageService.accessToken != null) {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const VerifyEmailPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const RegistrationPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages/verify_email_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
@ -17,7 +16,6 @@ class PasswordPage extends StatefulWidget {
|
||||
|
||||
class _PasswordPageState extends State<PasswordPage> {
|
||||
final BaseViewModel _vm = BaseViewModel();
|
||||
final StorageService _storageService = StorageService();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _passwordController1 = TextEditingController();
|
||||
|
||||
@ -204,7 +202,6 @@ class _PasswordPageState extends State<PasswordPage> {
|
||||
);
|
||||
}
|
||||
if (loggedin && mounted) {
|
||||
await _storageService.setAccountLevel(4);
|
||||
navigator.push(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/pages/password_page.dart';
|
||||
import 'package:app/pages/verify_email_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:app/util/validation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -26,18 +26,12 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
final accountLevel = await _storageService.accountLevel;
|
||||
if (accountLevel > 3 && mounted) {
|
||||
await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (builder) => const VerifyEmailPage()));
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
if (await _storageService.accountLevel < 3) {
|
||||
await _storageService.setAccountLevel(3);
|
||||
}
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -73,11 +67,12 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () async {
|
||||
await _storageService.setAccountLevel(2);
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const NotificationsPage()),
|
||||
(route) => false);
|
||||
},
|
||||
),
|
||||
iconTheme: IconThemeData(
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:app/model/services/auth_service.dart';
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/pages/start_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -22,18 +23,12 @@ class _SecurityPageState extends State<SecurityPage> {
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
final accountLevel = await _storageService.accountLevel;
|
||||
if (accountLevel > 1 && mounted) {
|
||||
await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (builder) => const NotificationsPage()));
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
if (await _storageService.accountLevel < 1) {
|
||||
await _storageService.setAccountLevel(1);
|
||||
}
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -63,11 +58,12 @@ class _SecurityPageState extends State<SecurityPage> {
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () async {
|
||||
await _storageService.setAccountLevel(0);
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const StartPage()),
|
||||
(route) => false);
|
||||
},
|
||||
),
|
||||
iconTheme: IconThemeData(color: CustomColors.primary),
|
||||
@ -117,14 +113,14 @@ class _SecurityPageState extends State<SecurityPage> {
|
||||
bool isAuthenticated =
|
||||
await AuthService.authenticateWithBiometrics();
|
||||
if (isAuthenticated) {
|
||||
await _storageService.setAccountLevel(2);
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const NotificationsPage()),
|
||||
);
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const NotificationsPage()),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
|
@ -1,166 +1,112 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/pages/agb_page.dart';
|
||||
import 'package:app/pages/security_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StartPage extends StatefulWidget {
|
||||
class StartPage extends StatelessWidget {
|
||||
const StartPage({super.key});
|
||||
|
||||
@override
|
||||
State<StartPage> createState() => _StartPageState();
|
||||
}
|
||||
|
||||
class _StartPageState extends State<StartPage> {
|
||||
final StorageService _storageService = StorageService();
|
||||
bool _loading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_init();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
int accountLevel = await _storageService.accountLevel;
|
||||
if (accountLevel > 0 && mounted) {
|
||||
await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (builder) => const SecurityPage()));
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: _loading
|
||||
? Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 150,
|
||||
),
|
||||
Hero(
|
||||
tag: 'logo',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
),
|
||||
),
|
||||
CircularProgressIndicator(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Scaffold(
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(color: CustomColors.primary),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Hero(
|
||||
tag: 'flow-icon',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Hallo. Digitale Spuren\nentfernen\nper Knopfdruck.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Mit uns finden Sie Ihre Digitalen Spuren und können diese entfernen.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () async {
|
||||
await _storageService.setAccountLevel(1);
|
||||
if (mounted) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const SecurityPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
const Text(
|
||||
'Mit der weiteren Nutzung stimmst du den folgenden Bedingungen zu:',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (builder) => AgbPage());
|
||||
},
|
||||
child: Text(
|
||||
'AGB - Datenschutzerklärung',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: CustomColors.primary),
|
||||
))
|
||||
],
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(color: CustomColors.primary),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Hero(
|
||||
tag: 'flow-icon',
|
||||
child: Image.asset(
|
||||
'assets/JPEG.jpg',
|
||||
height: 180,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Hallo. Digitale Spuren\nentfernen\nper Knopfdruck.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Mit uns finden Sie Ihre Digitalen Spuren und können diese entfernen.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const SecurityPage(),
|
||||
// builder: (builder) => SecurityPage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const SizedBox(
|
||||
height: 60,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
const Text(
|
||||
'Mit der weiteren Nutzung stimmst du den folgenden Bedingungen zu:',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context, builder: (builder) => AgbPage());
|
||||
},
|
||||
child: Text(
|
||||
'AGB - Datenschutzerklärung',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: CustomColors.primary),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:app/model/services/storage_service.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages/notifications_page.dart';
|
||||
import 'package:app/util/colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -18,6 +19,13 @@ class _VerifyEmailPageState extends State<VerifyEmailPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_init();
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
if (await _storageService.accountLevel < 4) {
|
||||
await _storageService.setAccountLevel(4);
|
||||
}
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
@ -50,11 +58,12 @@ class _VerifyEmailPageState extends State<VerifyEmailPage> {
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
color: CustomColors.primary,
|
||||
onPressed: () async {
|
||||
await _storageService.setAccountLevel(3);
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
onPressed: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const NotificationsPage()),
|
||||
(route) => false);
|
||||
},
|
||||
),
|
||||
iconTheme: IconThemeData(
|
||||
@ -63,95 +72,112 @@ class _VerifyEmailPageState extends State<VerifyEmailPage> {
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 20, 20, 16),
|
||||
child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 80,
|
||||
),
|
||||
const Text(
|
||||
'Verifizieren',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 80,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
),
|
||||
const Text(
|
||||
'Wir haben dir eine E-Mail geschickt.',
|
||||
textAlign: TextAlign.center,
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Bitte verifiziere deine E-Mail Adresse, dann geht es weiter.',
|
||||
textAlign: TextAlign.center,
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 80,
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
const Text(
|
||||
'Verifizieren',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2.0,
|
||||
fontSize: 25,
|
||||
),
|
||||
onPressed: () {},
|
||||
child: const SizedBox(
|
||||
height: 50,
|
||||
width: 100,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
),
|
||||
const Text(
|
||||
'Wir haben dir eine E-Mail geschickt.',
|
||||
textAlign: TextAlign.center,
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
'Bitte verifiziere deine E-Mail Adresse, dann geht es weiter.',
|
||||
textAlign: TextAlign.center,
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 80,
|
||||
),
|
||||
Hero(
|
||||
tag: 'flow-button',
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: CustomColors.primary,
|
||||
),
|
||||
onPressed: () {},
|
||||
child: const SizedBox(
|
||||
height: 50,
|
||||
width: 100,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Weiter',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 60,
|
||||
),
|
||||
const Text(
|
||||
'Noch keine E-Mail erhalten?',
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const Text(
|
||||
'Schon im Spam-Ordner nachgeschaut?',
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await _vm.resendVerification(context);
|
||||
},
|
||||
child: Text(
|
||||
'Erneut senden',
|
||||
const SizedBox(
|
||||
height: 60,
|
||||
),
|
||||
const Text(
|
||||
'Noch keine E-Mail erhalten?',
|
||||
// textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
const Text(
|
||||
'Schon im Spam-Ordner nachgeschaut?',
|
||||
// textAlign: TextAlign.center,
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 20,
|
||||
// ),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await _vm.resendVerification(context);
|
||||
},
|
||||
child: Text(
|
||||
'Erneut senden',
|
||||
// textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
],
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
const Text('Account versehentlich angelegt?'),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
TextButton(
|
||||
onPressed: () async {},
|
||||
child: Text(
|
||||
'Account löschen',
|
||||
style: TextStyle(
|
||||
color: CustomColors.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -1,221 +0,0 @@
|
||||
import 'package:app/model/services/backend_service.dart';
|
||||
import 'package:app/model/view_model/account_vm.dart';
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/pages_draft/login_overlay.dart';
|
||||
import 'package:app/pages_draft/persons_page.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/bottom_navigation.dart';
|
||||
import 'package:app/widgets/bottom_navigation_item.dart';
|
||||
import 'package:app/widgets/drawer.dart';
|
||||
import 'package:app/widgets/side_drawer_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class HomePage extends StatefulWidget {
|
||||
HomePage({super.key, required this.loggedOut});
|
||||
|
||||
bool loggedOut;
|
||||
|
||||
@override
|
||||
State<HomePage> createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_init();
|
||||
}
|
||||
|
||||
AccountViewModel vm = AccountViewModel();
|
||||
void _init() async {
|
||||
// _setLoading(true);
|
||||
// _setLoading(widget.loggedOut);
|
||||
// _loading = widget.loggedOut;
|
||||
// _loggedin = await BackendService.isLoggedIn;
|
||||
// if (!_loggedin) {
|
||||
// await BackendService.logout();
|
||||
// final navigator = Navigator.of(context);
|
||||
// navigator.pushAndRemoveUntil(
|
||||
// MaterialPageRoute(
|
||||
// builder: (builder) => HomePage(
|
||||
// loggedOut: true,
|
||||
// )),
|
||||
// (route) => false);
|
||||
// }
|
||||
_setLoading(false);
|
||||
}
|
||||
|
||||
_isLoggedIn(BuildContext context) async {
|
||||
bool logged = await vm.isLoggedIn(context);
|
||||
setState(() {
|
||||
_loggedin = logged;
|
||||
});
|
||||
}
|
||||
|
||||
void _setLoading(bool loading) {
|
||||
setState(() {
|
||||
_loading = loading;
|
||||
});
|
||||
}
|
||||
|
||||
bool _loading = true;
|
||||
bool _loggedin = false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
// flexibleSpace: Image.asset(
|
||||
// 'lib/assets/logo_300x200.png',
|
||||
// // height: 400,
|
||||
// ),
|
||||
),
|
||||
drawer: SideDrawer(
|
||||
children: [
|
||||
const Spacer(
|
||||
flex: 3,
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.question_answer,
|
||||
color: Colors.white,
|
||||
label: 'About',
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
label: 'Datenschutz',
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.apartment,
|
||||
color: Colors.white,
|
||||
label: 'Impressum',
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
if (_loggedin)
|
||||
SideDrawerItem(
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
_loading = true;
|
||||
});
|
||||
await BackendService.logout();
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => HomePage(
|
||||
loggedOut: true,
|
||||
)),
|
||||
(route) => false);
|
||||
setState(() {
|
||||
_loggedin = false;
|
||||
_loading = false;
|
||||
});
|
||||
},
|
||||
icon: Icons.logout,
|
||||
color: Colors.white,
|
||||
label: 'Logout',
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: BottomNavigation(
|
||||
children: [
|
||||
if (!_loggedin) ...[
|
||||
BottomNavigationItem(
|
||||
onPressed: () async {
|
||||
final bool res = await showLogin(context, registration: true);
|
||||
setState(() {
|
||||
_loggedin = res;
|
||||
});
|
||||
},
|
||||
icon: Icons.person_add_alt,
|
||||
color: Colors.white,
|
||||
label: 'Registrieren',
|
||||
),
|
||||
BottomNavigationItem(
|
||||
onPressed: () async {
|
||||
bool res = await showLogin(context);
|
||||
setState(() {
|
||||
_loggedin = res;
|
||||
// vm.isLoggedIn(context);
|
||||
});
|
||||
},
|
||||
icon: Icons.login,
|
||||
color: Colors.white,
|
||||
label: 'Login',
|
||||
),
|
||||
] else
|
||||
BottomNavigationItem(
|
||||
onPressed: () async {
|
||||
final navigator = Navigator.of(context);
|
||||
if (_loggedin) {
|
||||
navigator.push(MaterialPageRoute(
|
||||
builder: (builder) => const PersonsPage()));
|
||||
} else {
|
||||
navigator.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => const PersonsPage()),
|
||||
(route) => false);
|
||||
}
|
||||
},
|
||||
icon: Icons.person_search,
|
||||
color: Colors.white,
|
||||
label: 'Personen',
|
||||
),
|
||||
BottomNavigationItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.dashboard,
|
||||
color: Colors.white,
|
||||
label: 'Dashboard',
|
||||
),
|
||||
...[]
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 45, 16, 16),
|
||||
child: Center(
|
||||
child: ChangeNotifierProvider<BaseViewModel>(
|
||||
create: (context) => BaseViewModel(),
|
||||
child: Consumer<BaseViewModel>(builder: (context, value, child) {
|
||||
// _checkResponse(value.response);
|
||||
if (!widget.loggedOut) {
|
||||
_isLoggedIn(context);
|
||||
}
|
||||
return _loading
|
||||
? const CircularProgressIndicator(
|
||||
color: Colors.grey,
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
Image.asset(
|
||||
'lib/assets/logo_300x200.png',
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
Text(
|
||||
'Digitale Spuren auf Knopfdruck entfernen'
|
||||
.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 24,
|
||||
height: 1.6,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 6,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
})),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
@ -1,239 +0,0 @@
|
||||
import 'package:app/model/view_model/base_vm.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/bottom_navigation.dart';
|
||||
import 'package:app/widgets/bottom_navigation_item.dart';
|
||||
import 'package:app/widgets/side_drawer.dart';
|
||||
import 'package:app/widgets/side_drawer_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:app/util/validation.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
Future<bool> showLogin(BuildContext context,
|
||||
{bool registration = false}) async {
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final mailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
|
||||
BaseViewModel vm = BaseViewModel();
|
||||
bool submitted = false;
|
||||
bool loggedin = false;
|
||||
void login(BuildContext context) {
|
||||
if (formKey.currentState!.validate()) {
|
||||
submitted = true;
|
||||
FocusScope.of(context).unfocus();
|
||||
vm
|
||||
.login(context,
|
||||
email: mailController.text, password: passwordController.text)
|
||||
.then(
|
||||
(r) {
|
||||
if (r) {
|
||||
loggedin = r;
|
||||
Navigator.pop(context, true);
|
||||
}
|
||||
},
|
||||
);
|
||||
passwordController.clear();
|
||||
submitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
void register(BuildContext context) {
|
||||
if (formKey.currentState!.validate()) {
|
||||
submitted = true;
|
||||
vm
|
||||
.createAccount(
|
||||
context,
|
||||
email: mailController.text,
|
||||
password: passwordController.text,
|
||||
)
|
||||
.then(
|
||||
(r) {
|
||||
if (r) {
|
||||
loggedin = r;
|
||||
Navigator.pop(context, true);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await showModalBottomSheet(
|
||||
useSafeArea: true,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.black,
|
||||
context: context,
|
||||
builder: (builder) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
drawer: SideDrawer(
|
||||
children: [
|
||||
const Spacer(
|
||||
flex: 3,
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.question_answer,
|
||||
color: Colors.white,
|
||||
label: 'About',
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
label: 'Datenschutz',
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.apartment,
|
||||
color: Colors.white,
|
||||
label: 'Impressum',
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: BottomNavigation(
|
||||
children: [
|
||||
BottomNavigationItem(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, false);
|
||||
},
|
||||
icon: Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
label: 'Zurück',
|
||||
),
|
||||
BottomNavigationItem(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, false);
|
||||
},
|
||||
icon: Icons.home,
|
||||
color: Colors.white,
|
||||
label: 'Home',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
),
|
||||
const Image(
|
||||
width: 180,
|
||||
image: AssetImage(
|
||||
'lib/assets/logo_300x200.png',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Text(
|
||||
registration ? 'Registrieren' : 'Login',
|
||||
style: const TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 24,
|
||||
height: 1.6,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 6,
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider<BaseViewModel>(
|
||||
create: (context) => BaseViewModel(),
|
||||
child: Consumer<BaseViewModel>(
|
||||
builder: (context, value, child) => Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
TextFormField(
|
||||
// autofocus: true,
|
||||
// inputFormatters: [
|
||||
// FilteringTextInputFormatter.allow(
|
||||
// emailRegExp,
|
||||
// ),
|
||||
// ],
|
||||
controller: mailController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'E-Mail Adresse',
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidEmail) {
|
||||
return 'Bitte eine gültige E-Mail Adresse eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
// inputFormatters: [
|
||||
// FilteringTextInputFormatter.allow(
|
||||
// passwordRegExp,
|
||||
// ),
|
||||
// ],
|
||||
controller: passwordController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Passwort',
|
||||
),
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidPassword) {
|
||||
return 'Bitte geben Sie Ihr Passwort ein';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: !submitted
|
||||
? !registration
|
||||
? () {
|
||||
login(context);
|
||||
}
|
||||
: () {
|
||||
register(context);
|
||||
}
|
||||
: null,
|
||||
child: const Icon(Icons.login),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
return loggedin;
|
||||
}
|
@ -1,339 +0,0 @@
|
||||
import 'package:app/model/view_model/persons_vm.dart';
|
||||
import 'package:app/pb/google/protobuf/timestamp.pb.dart';
|
||||
import 'package:app/pb/person.pb.dart';
|
||||
import 'package:app/util/validation.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/bottom_navigation.dart';
|
||||
import 'package:app/widgets/bottom_navigation_item.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
Future<Person> showPerson(BuildContext context, {Person? person}) async {
|
||||
PersonsViewModel vm = PersonsViewModel();
|
||||
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final firstnameController = TextEditingController();
|
||||
final lastnameController = TextEditingController();
|
||||
final cityController = TextEditingController();
|
||||
final zipController = TextEditingController();
|
||||
final streetController = TextEditingController();
|
||||
final countryController = TextEditingController();
|
||||
final birthdayController = TextEditingController();
|
||||
|
||||
Future<void> _init() async {
|
||||
if (person == null) {
|
||||
person ??= Person();
|
||||
// person ??= Person(accountId: await BackendService.accountId);
|
||||
} else {
|
||||
firstnameController.text = person!.firstname;
|
||||
lastnameController.text = person!.lastname;
|
||||
cityController.text = person!.city;
|
||||
zipController.text = person!.zip;
|
||||
streetController.text = person!.street;
|
||||
countryController.text = person!.country;
|
||||
birthdayController.text =
|
||||
DateFormat('dd.MM.yyyy').format(person!.birthday.toDateTime());
|
||||
}
|
||||
}
|
||||
|
||||
await _init();
|
||||
|
||||
void _updateData() {
|
||||
person!.firstname = firstnameController.text;
|
||||
person!.lastname = lastnameController.text;
|
||||
person!.city = cityController.text;
|
||||
person!.street = streetController.text;
|
||||
person!.zip = zipController.text;
|
||||
person!.country = countryController.text;
|
||||
}
|
||||
|
||||
Future<void> createPerson(BuildContext context) async {
|
||||
final navigator = Navigator.of(context);
|
||||
_updateData();
|
||||
person!.id = Int64(0);
|
||||
person = await vm.createPerson(context,
|
||||
firstname: person!.firstname,
|
||||
lastname: person!.lastname,
|
||||
street: person!.street,
|
||||
zip: person!.zip,
|
||||
city: person!.city,
|
||||
country: person!.country,
|
||||
birthday: person!.birthday);
|
||||
|
||||
if (person!.id != 0) {
|
||||
navigator.pop(person);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updatePerson(BuildContext context) async {
|
||||
final navigator = Navigator.of(context);
|
||||
_updateData();
|
||||
final personUpdate = await vm.updatePerson(context,
|
||||
id: person!.id,
|
||||
firstname: person!.firstname != firstnameController.text
|
||||
? person!.firstname
|
||||
: null,
|
||||
lastname: person!.lastname != lastnameController.text
|
||||
? person!.lastname
|
||||
: null,
|
||||
street: person!.street != streetController.text ? person!.street : null,
|
||||
zip: person!.zip != zipController.text ? person!.zip : null,
|
||||
city: person!.city != cityController.text ? person!.city : null,
|
||||
country:
|
||||
person!.country != countryController.text ? person!.country : null,
|
||||
birthday:
|
||||
DateFormat('dd.MM.yyyy').format(person!.birthday.toDateTime()) !=
|
||||
birthdayController.text
|
||||
? person!.birthday
|
||||
: null);
|
||||
|
||||
if (personUpdate != person) {
|
||||
navigator.pop(person);
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: use_build_context_synchronously
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (builder) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
bottomNavigationBar: BottomNavigation(
|
||||
hideMenu: true,
|
||||
children: [
|
||||
BottomNavigationItem(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, false);
|
||||
},
|
||||
icon: Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
label: 'Zurück',
|
||||
),
|
||||
BottomNavigationItem(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, false);
|
||||
},
|
||||
icon: Icons.home,
|
||||
color: Colors.white,
|
||||
label: 'Home',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
),
|
||||
Text(
|
||||
person!.id == 0 ? 'Person anlegen' : 'Person anpassen',
|
||||
style: const TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 24,
|
||||
height: 1.6,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 6),
|
||||
),
|
||||
ChangeNotifierProvider<PersonsViewModel>(
|
||||
create: (context) => PersonsViewModel(),
|
||||
child: Consumer<PersonsViewModel>(
|
||||
builder: (context, value, child) => Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
TextFormField(
|
||||
controller: firstnameController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
suffix: Text('Vorname'),
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Vorname',
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte einen gültigen Vornamen eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
controller: lastnameController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
suffix: Text('Nachname'),
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Nachname',
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte einen gültigen Nachnamen eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
readOnly: true,
|
||||
onTap: () async {
|
||||
DateTime? pickedDate = await showDatePicker(
|
||||
context: context,
|
||||
locale: const Locale('de', 'DE'),
|
||||
initialDate: DateTime.now(),
|
||||
firstDate: DateTime(1930),
|
||||
lastDate: DateTime(DateTime.now().year + 1),
|
||||
builder: (context, child) => Theme(
|
||||
data: ThemeData.dark(),
|
||||
child: child != null ? child : Text(''),
|
||||
),
|
||||
);
|
||||
|
||||
if (pickedDate != null) {
|
||||
person!.birthday =
|
||||
Timestamp.fromDateTime(pickedDate);
|
||||
birthdayController.text =
|
||||
DateFormat('dd.MM.yyyy')
|
||||
.format(pickedDate);
|
||||
}
|
||||
},
|
||||
controller: birthdayController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
suffix: Text('Geburtstag'),
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Geburtstag',
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
// validator: (value) {
|
||||
// if (value == null || !value.isValidName) {
|
||||
// return 'Bitte einen gültigen Nachnamen eingeben';
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
),
|
||||
TextFormField(
|
||||
controller: streetController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
suffix: Text('Straße'),
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Straße mit Hausnummer',
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte eine gültige Straße mit Hausnummer eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
controller: zipController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
suffix: Text('PLZ'),
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'PLZ',
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte eine gültige PLZ eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
controller: cityController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
suffix: Text('Stadt'),
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Stadt',
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte eine gültige Stadt eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
controller: countryController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
suffix: Text('Land'),
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Land',
|
||||
),
|
||||
keyboardType: TextInputType.name,
|
||||
validator: (value) {
|
||||
if (value == null || !value.isValidName) {
|
||||
return 'Bitte ein gültiges Land eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
person!.id.isZero
|
||||
? await createPerson(context)
|
||||
: await updatePerson(context);
|
||||
},
|
||||
child: const Icon(Icons.update),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
useSafeArea: true,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.black);
|
||||
return person!;
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
import 'package:app/model/apis/api_response.dart';
|
||||
import 'package:app/model/services/backend_service.dart';
|
||||
import 'package:app/model/view_model/persons_vm.dart';
|
||||
import 'package:app/pages_draft/home_page.dart';
|
||||
import 'package:app/pages_draft/person_details_page.dart';
|
||||
import 'package:app/pb/person.pb.dart';
|
||||
import 'package:app/util/validation.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/bottom_navigation.dart';
|
||||
import 'package:app/widgets/bottom_navigation_item.dart';
|
||||
import 'package:app/widgets/side_drawer.dart';
|
||||
import 'package:app/widgets/side_drawer_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class PersonsPage extends StatefulWidget {
|
||||
const PersonsPage({super.key});
|
||||
|
||||
@override
|
||||
State<PersonsPage> createState() => _PersonsPageState();
|
||||
}
|
||||
|
||||
class _PersonsPageState extends State<PersonsPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// _init();
|
||||
}
|
||||
|
||||
// void _init() async {
|
||||
// _setLoading(true);
|
||||
// _loggedin = await BackendService.isLoggedIn;
|
||||
// _setLoading(false);
|
||||
// }
|
||||
|
||||
// void _setLoading(bool loading) {
|
||||
// setState(() {
|
||||
// _loading = loading;
|
||||
// });
|
||||
// }
|
||||
|
||||
void _checkResponse(ApiResponse response) {
|
||||
if (response.status == Status.ERROR &&
|
||||
(response.message!.contains('unauthenticated') ||
|
||||
response.message!.contains('blocked'))) {
|
||||
BackendService.logout();
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => HomePage(
|
||||
loggedOut: true,
|
||||
)),
|
||||
(route) => false);
|
||||
}
|
||||
}
|
||||
|
||||
bool _loading = false;
|
||||
bool _loggedin = false;
|
||||
List<Person> persons = [];
|
||||
|
||||
PersonsViewModel vm = PersonsViewModel();
|
||||
|
||||
void listPersons(BuildContext context) async {
|
||||
persons = await vm.listPersons();
|
||||
}
|
||||
|
||||
List<Widget> _personsList(List<Person> persons) {
|
||||
persons.sort((a, b) {
|
||||
final comp = a.lastname.compareTo(b.lastname);
|
||||
if (comp != 0) {
|
||||
return comp;
|
||||
}
|
||||
return a.firstname.compareTo(b.firstname);
|
||||
});
|
||||
final List<Widget> list = [];
|
||||
for (var p in persons) {
|
||||
list.add(TextButton(
|
||||
onPressed: () async {
|
||||
final Person per = await showPerson(context, person: p);
|
||||
if (!per.id.isZero && !persons.contains(per)) {
|
||||
setState(() {
|
||||
this.persons.add(per);
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Card(
|
||||
shape:
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
color: const Color.fromARGB(100, 89, 88, 88),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 14),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 40,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
p.lastname.titleCase,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
// overflow: TextOverflow.fade,
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
p.firstname.titleCase,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
textAlign: TextAlign.start,
|
||||
// overflow: TextOverflow.fade,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Text('STATUS')
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () async {
|
||||
final p = await showPerson(context);
|
||||
if (!p.id.isZero && !persons.contains(p)) {
|
||||
setState(() {
|
||||
persons.add(p);
|
||||
});
|
||||
}
|
||||
},
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
drawer: SideDrawer(
|
||||
children: [
|
||||
const Spacer(
|
||||
flex: 3,
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.question_answer,
|
||||
color: Colors.white,
|
||||
label: 'About',
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
label: 'Datenschutz',
|
||||
),
|
||||
SideDrawerItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.apartment,
|
||||
color: Colors.white,
|
||||
label: 'Impressum',
|
||||
),
|
||||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
if (_loggedin)
|
||||
SideDrawerItem(
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
_loading = true;
|
||||
});
|
||||
await BackendService.logout();
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (builder) => HomePage(
|
||||
loggedOut: true,
|
||||
)),
|
||||
(route) => false);
|
||||
setState(() {
|
||||
_loggedin = false;
|
||||
_loading = false;
|
||||
});
|
||||
},
|
||||
icon: Icons.logout,
|
||||
color: Colors.white,
|
||||
label: 'Logout',
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: BottomNavigation(
|
||||
children: [
|
||||
BottomNavigationItem(
|
||||
onPressed: () {},
|
||||
icon: Icons.dashboard,
|
||||
color: Colors.white,
|
||||
label: 'Dashboard',
|
||||
),
|
||||
BottomNavigationItem(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon: Icons.home,
|
||||
color: Colors.white,
|
||||
label: 'Home',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: ChangeNotifierProvider<PersonsViewModel>(
|
||||
create: (context) => PersonsViewModel(),
|
||||
child: Consumer<PersonsViewModel>(
|
||||
builder: (context, value, child) {
|
||||
_checkResponse(value.response);
|
||||
if (persons.isEmpty) {
|
||||
listPersons(context);
|
||||
}
|
||||
return _loading
|
||||
? const CircularProgressIndicator(
|
||||
color: Colors.grey,
|
||||
)
|
||||
: value.response.status == Status.COMPLETED
|
||||
? value.response.data.length > 0
|
||||
? ListView(children: _personsList(persons))
|
||||
: const Text('Noch keine Personen angelegt')
|
||||
: const Text('Lade Daten...');
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,298 +0,0 @@
|
||||
import 'package:app/pb/account_info.pb.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/loading_widget.dart';
|
||||
import 'package:app/widgets/side_drawer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DashboardPage extends StatefulWidget {
|
||||
const DashboardPage({
|
||||
super.key,
|
||||
// required this.client,
|
||||
});
|
||||
|
||||
// final GClient client;
|
||||
|
||||
@override
|
||||
State<DashboardPage> createState() => _DashboardPageState();
|
||||
}
|
||||
|
||||
class _DashboardPageState extends State<DashboardPage> {
|
||||
bool _loading = false;
|
||||
late AccountInfo accountInfo;
|
||||
|
||||
void _setLoading(bool loading) {
|
||||
setState(() {
|
||||
_loading = loading;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_setLoading(true);
|
||||
// widget.client.getAccountInfo(
|
||||
// GetAccountInfoRequest(
|
||||
// accountId: widget.client.session.accountId,
|
||||
// ),
|
||||
// onError: ({String? msg}) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: const Text('AccountInfo konnte nicht geladen werden'),
|
||||
// action: msg != null
|
||||
// ? SnackBarAction(
|
||||
// label: 'Details',
|
||||
// textColor: Colors.grey,
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return AlertDialog(
|
||||
// content: Text(
|
||||
// msg,
|
||||
// textAlign: TextAlign.center,
|
||||
// style: const TextStyle(color: Colors.black),
|
||||
// ),
|
||||
// icon: const Icon(
|
||||
// Icons.warning,
|
||||
// color: Colors.red,
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// })
|
||||
// : null,
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ).then((value) {
|
||||
// accountInfo = value.accountInfo;
|
||||
// _setLoading(false);
|
||||
// });
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
flexibleSpace: Image.asset(
|
||||
'lib/assets/logo_300x200.png',
|
||||
height: 80,
|
||||
),
|
||||
),
|
||||
drawer: Builder(builder: (context) {
|
||||
return SideDrawer(
|
||||
children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// if (widget.client.session.accessToken != null)
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// widget.client.session.accessToken = null;
|
||||
// widget.client.session
|
||||
// .removeSession(widget.client.session.sessionId!);
|
||||
|
||||
// Navigator.of(context).pushAndRemoveUntil(
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) =>
|
||||
// StartPage(client: widget.client),
|
||||
// ),
|
||||
// (route) => false);
|
||||
// },
|
||||
// child: const Row(
|
||||
// children: [
|
||||
// Text(
|
||||
// 'Log out',
|
||||
// style: TextStyle(fontSize: 20),
|
||||
// ),
|
||||
// Spacer(),
|
||||
// Icon(
|
||||
// Icons.logout,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
// bottomNavigationBar: Builder(
|
||||
// builder: (context) {
|
||||
// return BottomBar(
|
||||
// children: widget.client.session.accessToken != null
|
||||
// ? [
|
||||
// BottomNavigationBarItem(
|
||||
// backgroundColor: Colors.white,
|
||||
// label: 'Personen',
|
||||
// icon: Column(
|
||||
// children: [
|
||||
// IconButton(
|
||||
// onPressed: () =>
|
||||
// Scaffold.of(context).openDrawer(),
|
||||
// icon: const Icon(
|
||||
// Icons.group,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// const Text(
|
||||
// 'Personen',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontSize: 16,
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BottomNavigationBarItem(
|
||||
// backgroundColor: Colors.white,
|
||||
// label: 'Home',
|
||||
// icon: Column(
|
||||
// children: [
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// Navigator.of(context).push(
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => StartPage(
|
||||
// client: widget.client,
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// Icons.home,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// const Text(
|
||||
// 'Home',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontSize: 16,
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BottomNavigationBarItem(
|
||||
// backgroundColor: Colors.white,
|
||||
// label: 'Menu',
|
||||
// icon: IconButton(
|
||||
// onPressed: () {
|
||||
// Scaffold.of(context).openDrawer();
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// Icons.menu,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// ]
|
||||
// : [
|
||||
// BottomNavigationBarItem(
|
||||
// label: 'back',
|
||||
// backgroundColor: Colors.white,
|
||||
// icon: IconButton(
|
||||
// onPressed: () {},
|
||||
// icon: const Icon(
|
||||
// Icons.arrow_back,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// BottomNavigationBarItem(
|
||||
// backgroundColor: Colors.white,
|
||||
// label: 'Menu',
|
||||
// icon: IconButton(
|
||||
// onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
// icon: const Icon(
|
||||
// Icons.menu,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
body: !_loading
|
||||
? Background(
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 48,
|
||||
),
|
||||
Text(
|
||||
'Willkommen ${accountInfo.firstname} ${accountInfo.lastname}!',
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: const LoadingWidget(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,287 +0,0 @@
|
||||
import 'package:app/model/services/backend_service.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/bottom_bar.dart';
|
||||
import 'package:app/widgets/loading_widget.dart';
|
||||
import 'package:app/widgets/side_drawer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
const LoginPage({
|
||||
super.key,
|
||||
// required this.client,
|
||||
// required this.onChangePage,
|
||||
});
|
||||
|
||||
// final GClient client;
|
||||
// void Function(Pages page) onChangePage;
|
||||
|
||||
@override
|
||||
State<LoginPage> createState() => _LoginPageState();
|
||||
}
|
||||
|
||||
class _LoginPageState extends State<LoginPage> {
|
||||
bool _loading = false;
|
||||
final List<BottomNavigationBarItem> bottombarButtons = [];
|
||||
|
||||
// List<BottomNavigationBarItem> _selectedBottomBarButtons = bottomBarButtons;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_addBottomBarButtons();
|
||||
}
|
||||
|
||||
void _addBottomBarButtons() {
|
||||
bottombarButtons.addAll([
|
||||
const BottomNavigationBarItem(
|
||||
label: 'back',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
void _setLoading(bool loading) {
|
||||
setState(() {
|
||||
_loading = loading;
|
||||
});
|
||||
}
|
||||
|
||||
// final GClient client = GClient();
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final mailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
// flexibleSpace: Image.asset(
|
||||
// 'lib/assets/logo_300x200.png',
|
||||
// height: 80,
|
||||
// ),
|
||||
),
|
||||
bottomNavigationBar: BottomBar(
|
||||
children: [
|
||||
BottomNavigationBarItem(
|
||||
label: 'back',
|
||||
backgroundColor: Colors.white,
|
||||
icon: IconButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
icon: const Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
drawer: SideDrawer(children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
]),
|
||||
body: !_loading
|
||||
? Form(
|
||||
key: _formKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 100, 16, 16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Image(
|
||||
width: 180,
|
||||
image: AssetImage(
|
||||
'lib/assets/logo_300x200.png',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Login',
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 24,
|
||||
height: 1.6,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 6,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
TextFormField(
|
||||
// style: TextStyle(
|
||||
// color: Theme.of(context).colorScheme.primary,
|
||||
// ),
|
||||
controller: mailController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'E-Mail Adresse',
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Bitte eine gültige E-Mail Adresse eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
controller: passwordController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Passwort',
|
||||
),
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Bitte geben Sie Ihr Passwort ein';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
// final navigator = Navigator.of(context);
|
||||
_setLoading(true);
|
||||
// BackendService.login(
|
||||
// email: mailController.text,
|
||||
// password: passwordController.text,
|
||||
// ).then(
|
||||
// (r) {
|
||||
// if (r) {
|
||||
// Navigator.pop(context);
|
||||
// Navigator.pop(context);
|
||||
// // Navigator.pushAndRemoveUntil(
|
||||
// // context,
|
||||
// // MaterialPageRoute(
|
||||
// // builder: (ctx) => const StartPage(
|
||||
// // // client: widget.client,
|
||||
// // ),
|
||||
// // ),
|
||||
// // (ctx) => false,
|
||||
// // );
|
||||
// // widget.onChangePage(
|
||||
// // Pages.dashboard,
|
||||
// // );
|
||||
// }
|
||||
// // _setLoading(false);
|
||||
// },
|
||||
// );
|
||||
}
|
||||
},
|
||||
child: const Icon(Icons.login))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: const LoadingWidget(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,221 +0,0 @@
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/bottom_bar.dart';
|
||||
import 'package:app/widgets/loading_widget.dart';
|
||||
import 'package:app/widgets/side_drawer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RegisterPage extends StatefulWidget {
|
||||
const RegisterPage({
|
||||
super.key,
|
||||
// required this.client,
|
||||
});
|
||||
|
||||
// final GClient client;
|
||||
|
||||
@override
|
||||
State<RegisterPage> createState() => _RegisterPageState();
|
||||
}
|
||||
|
||||
class _RegisterPageState extends State<RegisterPage> {
|
||||
bool _loading = false;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final mailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
|
||||
void _setLoading(bool loading) {
|
||||
setState(() {
|
||||
_loading = loading;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
flexibleSpace: Image.asset(
|
||||
'lib/assets/logo_300x200.png',
|
||||
height: 80,
|
||||
),
|
||||
),
|
||||
drawer: Builder(builder: (context) {
|
||||
return SideDrawer(
|
||||
children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
bottomNavigationBar: BottomBar(
|
||||
children: [
|
||||
BottomNavigationBarItem(
|
||||
label: 'back',
|
||||
backgroundColor: Colors.white,
|
||||
icon: IconButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
icon: const Icon(
|
||||
Icons.arrow_back,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: !_loading
|
||||
? Form(
|
||||
key: _formKey,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 100, 16, 16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Image(
|
||||
width: 180,
|
||||
image: AssetImage(
|
||||
'lib/assets/logo_300x200.png',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Text(
|
||||
'Registrieren',
|
||||
style: TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 24,
|
||||
height: 1.6,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 6,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
TextFormField(
|
||||
controller: mailController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'E-Mail Adresse',
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Bitte eine gültige E-Mail Adresse eingeben';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
controller: passwordController,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Color.fromARGB(30, 255, 255, 255),
|
||||
filled: true,
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white38,
|
||||
),
|
||||
hintText: 'Passwort',
|
||||
),
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Bitte geben Sie Ihr Passwort ein';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
// _setLoading(true);
|
||||
}
|
||||
},
|
||||
child: const Icon(Icons.login))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: const LoadingWidget()),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,370 +0,0 @@
|
||||
import 'package:app/model/apis/api_response.dart';
|
||||
import 'package:app/model/view_model/account_vm.dart';
|
||||
import 'package:app/pages_old/login_page.dart';
|
||||
import 'package:app/pb/account.pb.dart';
|
||||
import 'package:app/widgets/background.dart';
|
||||
import 'package:app/widgets/bottom_bar.dart';
|
||||
import 'package:app/widgets/side_drawer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:core';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class StartPage extends StatefulWidget {
|
||||
const StartPage({
|
||||
super.key,
|
||||
// required this.client,
|
||||
});
|
||||
|
||||
// GClient client;
|
||||
|
||||
@override
|
||||
State<StartPage> createState() => _StartPageState();
|
||||
}
|
||||
|
||||
class _StartPageState extends State<StartPage> {
|
||||
final List<BottomNavigationBarItem> bottombarButtons = [];
|
||||
|
||||
// void _updateClient(GClient c) {
|
||||
// setState(() {
|
||||
// widget.client = c;
|
||||
// });
|
||||
// }
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
SnackBar _snackBar(BuildContext context, String message, String label,
|
||||
void Function() action) {
|
||||
ScaffoldMessenger.of(context).removeCurrentSnackBar();
|
||||
// ScaffoldMessenger.of(context).clearSnackBars();
|
||||
return SnackBar(
|
||||
content: Text(
|
||||
message,
|
||||
style: const TextStyle(color: Colors.black),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
action: SnackBarAction(
|
||||
label: label,
|
||||
onPressed: action,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
child: ChangeNotifierProvider<AccountViewModel>(
|
||||
create: (context) => AccountViewModel(),
|
||||
child: Consumer<AccountViewModel>(builder: (context, value, child) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
),
|
||||
drawer: Builder(builder: (context) {
|
||||
return SideDrawer(children: [
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'About',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.question_answer,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Datenschutz',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.privacy_tip,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Impressum',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.apartment,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
value.logout();
|
||||
// ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
_snackBar(
|
||||
context,
|
||||
value.response.message != null
|
||||
? value.response.message!
|
||||
: value.response.status.toString(),
|
||||
value.response.status.toString(),
|
||||
() {
|
||||
print('asdf');
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const Row(
|
||||
children: [
|
||||
Text(
|
||||
'Log out',
|
||||
style: TextStyle(fontSize: 20),
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.logout,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 250,
|
||||
)
|
||||
]);
|
||||
}),
|
||||
bottomNavigationBar: Builder(builder: (context) {
|
||||
return BottomBar(
|
||||
// onTap: (value) => _bottomBarAction(value),
|
||||
children: value.response.data != null
|
||||
? [
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Personen',
|
||||
icon: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.group,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
'Personen',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Dashboard',
|
||||
icon: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
Icons.dashboard,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
'Dashboard',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
)
|
||||
]
|
||||
: [
|
||||
BottomNavigationBarItem(
|
||||
label: 'register',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
Icons.login,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
'Registrieren',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: 'login',
|
||||
backgroundColor: Colors.white,
|
||||
icon: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (builder) =>
|
||||
const LoginPage()));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.login,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
'Login',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
backgroundColor: Colors.white,
|
||||
label: 'Menu',
|
||||
icon: IconButton(
|
||||
onPressed: () => Scaffold.of(context).openDrawer(),
|
||||
icon: const Icon(
|
||||
Icons.menu,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
body: Column(
|
||||
children: [
|
||||
if (value.response.status == Status.COMPLETED &&
|
||||
value.response.data != null &&
|
||||
!(value.response.data as Account).emailVerified)
|
||||
Card(
|
||||
color: Colors.orange,
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
const Text(
|
||||
'E-Mail ist noch nicht verifiziert.',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 14),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(
|
||||
Icons.restore,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Image(
|
||||
image: AssetImage(
|
||||
'lib/assets/logo_300x200.png',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
Text(
|
||||
'Digitale Spuren auf Knopfdruck entfernen'
|
||||
.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: 24,
|
||||
height: 1.6,
|
||||
fontWeight: FontWeight.normal,
|
||||
letterSpacing: 6,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// ScaffoldMessenger.of(context).clearSnackBars();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
_snackBar(
|
||||
context,
|
||||
value.response.message != null
|
||||
? value.response.message!
|
||||
: value.response.status.toString(),
|
||||
value.response.status.toString(),
|
||||
() {
|
||||
print('asdf');
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const Text('asdf'))
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|