From 9caca30e1e44435f0d3d5073abc9e3abe4ff32fd Mon Sep 17 00:00:00 2001 From: louiscklaw Date: Wed, 4 Jun 2025 18:04:47 +0800 Subject: [PATCH] update demo-dictionary-app, --- .../assets/DemoDictionaryApp/icon/favicon.png | Bin 0 -> 930 bytes .../assets/DemoDictionaryApp/icon/icon.png | Bin 0 -> 23794 bytes .../assets/DemoDictionaryApp/shapes.svg | 1 + 03_source/mobile/src/App.tsx | 2 +- .../pages/DemoDictionaryApp/AppPages/Tab1.jsx | 121 ++++--- .../pages/DemoDictionaryApp/AppPages/Tab2.jsx | 86 ++--- .../pages/DemoDictionaryApp/AppPages/Tab3.jsx | 45 +++ .../components/NoFavourites.jsx | 22 ++ .../DemoDictionaryApp/components/NoSearch.jsx | 23 ++ .../DemoDictionaryApp/components/WordCard.jsx | 129 +++++++ .../components/WordCardHeading.jsx | 10 + .../components/WordMeaning.jsx | 18 + .../components/WordModal.jsx | 122 +++++++ .../src/pages/DemoDictionaryApp/index.tsx | 34 +- .../DemoDictionaryApp/store/Selectors.js | 8 + .../DemoDictionaryApp/store/WordStore.js | 29 ++ .../pages/DemoDictionaryApp/store/index.js | 1 + .../src/pages/DemoDictionaryApp/style.scss | 317 +++++++++++++----- .../src/pages/DemoDictionaryApp/utils.js | 21 ++ 03_source/mobile/src/pages/DemoList/index.tsx | 8 + .../AppPages/Tab1.jsx | 0 .../AppPages/Tab2.jsx | 0 .../CurrentWeather/WeatherProperty.tsx | 0 .../components/CurrentWeather/index.tsx | 0 .../components/SkeletonDashboard/index.tsx | 0 .../{WeatherDemo => DemoWeatherApp}/index.tsx | 0 .../style.scss | 0 .../CurrentWeather/WeatherProperty.tsx | 62 ---- .../components/CurrentWeather/index.tsx | 48 --- .../components/SkeletonDashboard/index.tsx | 117 ------- 30 files changed, 799 insertions(+), 425 deletions(-) create mode 100644 03_source/mobile/public/assets/DemoDictionaryApp/icon/favicon.png create mode 100644 03_source/mobile/public/assets/DemoDictionaryApp/icon/icon.png create mode 100644 03_source/mobile/public/assets/DemoDictionaryApp/shapes.svg create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab3.jsx create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/components/NoFavourites.jsx create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/components/NoSearch.jsx create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/components/WordCard.jsx create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/components/WordCardHeading.jsx create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/components/WordMeaning.jsx create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/components/WordModal.jsx create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/store/Selectors.js create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/store/WordStore.js create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/store/index.js create mode 100644 03_source/mobile/src/pages/DemoDictionaryApp/utils.js rename 03_source/mobile/src/pages/{WeatherDemo => DemoWeatherApp}/AppPages/Tab1.jsx (100%) rename 03_source/mobile/src/pages/{WeatherDemo => DemoWeatherApp}/AppPages/Tab2.jsx (100%) rename 03_source/mobile/src/pages/{DemoDictionaryApp => DemoWeatherApp}/components/CurrentWeather/WeatherProperty.tsx (100%) rename 03_source/mobile/src/pages/{DemoDictionaryApp => DemoWeatherApp}/components/CurrentWeather/index.tsx (100%) rename 03_source/mobile/src/pages/{DemoDictionaryApp => DemoWeatherApp}/components/SkeletonDashboard/index.tsx (100%) rename 03_source/mobile/src/pages/{WeatherDemo => DemoWeatherApp}/index.tsx (100%) rename 03_source/mobile/src/pages/{WeatherDemo => DemoWeatherApp}/style.scss (100%) delete mode 100644 03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/WeatherProperty.tsx delete mode 100644 03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/index.tsx delete mode 100644 03_source/mobile/src/pages/WeatherDemo/components/SkeletonDashboard/index.tsx diff --git a/03_source/mobile/public/assets/DemoDictionaryApp/icon/favicon.png b/03_source/mobile/public/assets/DemoDictionaryApp/icon/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..51888a7bbdb59f04c29c548523eb2638c1c954f5 GIT binary patch literal 930 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

HKF0m1(Dz`$p z;8CD!yy4yS&%huDZw^`#7X1~({40AY?A@;aQb2bp*K!}~$*wM4vC(nb{=`iuX;P!a z`jVq8Cq7Gedz9(`&R=lGI%Q^=`nqV7kedDBfv(ux%TYv{a@Aewg_aiV_Td6OG~*Y9 zJBKtq4oyC%eY3z8BTp?wi~ZR5*F$nM z8EYn2Y|AolySbx!4?JDR@A`}U@-+aHLQhnPmKi1r?e#JZp}ljBeM2siQ8`^;d9q$l z4r!^#d=>l!ZQap^xAQv#76Z8iF2!PcUw;eQPyZ$6lnm)-qM(UcfC_a``iMRR0a3%K zpt;%)=cL>B84}vCUj1nI>%4Vqf;P_uj`oOzvjH@?C4mOxBWw1U!xSX&?nA%~J?S>q z`Drs@DX0i_&|vma{EMU$voU!m&T=**gzTsG{7#s6e&UYCe1T0nO4x^oj_W}xAZfJ- zi*13eG}V_CK!$q)_MML#!af0~3v~3jrAa#k}puLda%RcUZ zS-@CPF!SM|`L1Bw=QrASiWbjR(Y&+2yAy?KgG~WWm`yAA-@oy`EwnL=Xj@zSVFHKJ zppEeSILSZlV`%l_ diff --git a/03_source/mobile/src/App.tsx b/03_source/mobile/src/App.tsx index 894c129..52fe519 100644 --- a/03_source/mobile/src/App.tsx +++ b/03_source/mobile/src/App.tsx @@ -66,7 +66,7 @@ import PrivacyAgreement from './pages/PrivacyAgreement'; import AppRoute from './AppRoute'; // import DemoReactShop from './pages/DemoReactShop'; -import DemoWeatherApp from './pages/WeatherDemo'; +import DemoWeatherApp from './pages/DemoWeatherApp'; import DemoClubHouse from './pages/DemoClubHouse'; import DemoScoreBoard from './pages/DemoScoreBoard'; import DemoQuoteApp from './pages/DemoQuoteApp'; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab1.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab1.jsx index a6f4101..f107663 100644 --- a/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab1.jsx +++ b/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab1.jsx @@ -1,8 +1,13 @@ import { IonButton, IonButtons, + IonCard, + IonCardContent, + IonCardSubtitle, + IonCardTitle, IonCol, IonContent, + IonGrid, IonHeader, IonIcon, IonPage, @@ -11,54 +16,27 @@ import { IonToolbar, useIonRouter, } from '@ionic/react'; +import { bookOutline, chevronBackOutline, heart, search } from 'ionicons/icons'; +import { useStoreState } from 'pullstate'; +import { useRef } from 'react'; +import { WordStore } from '../store'; +import { getFavourites, getSearchCount } from '../store/Selectors'; -import { Geolocation } from '@capacitor/geolocation'; -import { useEffect, useState } from 'react'; -import { SkeletonDashboard } from '../components/SkeletonDashboard'; -import { chevronBackOutline, refreshOutline } from 'ionicons/icons'; -import { CurrentWeather } from '../components/CurrentWeather'; - -function Tab1() { +const Tab1 = () => { const router = useIonRouter(); - - const [currentWeather, setCurrentWeather] = useState(false); - - useEffect(() => { - getCurrentPosition(); - }, []); - - const getCurrentPosition = async () => { - setCurrentWeather(false); - const coordinates = await Geolocation.getCurrentPosition(); - getAddress(coordinates.coords); - }; - - const getAddress = async (coords) => { - const query = `${coords.latitude},${coords.longitude}`; - const response = await fetch( - `https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}` - ); - - const data = await response.json(); - console.log(data); - setCurrentWeather(data); - }; + const pageRef = useRef(); + const favourites = useStoreState(WordStore, getFavourites); + const searchCount = useStoreState(WordStore, getSearchCount); function handleBackClick() { router.goBack(); } return ( - + - My Weather - - - getCurrentPosition()}> - - - + Dashboard handleBackClick()}> @@ -71,25 +49,66 @@ function Tab1() { Dashboard + + + handleBackClick()}> + + + - - -

Here's your location based weather

- - + + + + + + + Ionic Dictionary App +

Based on the English language

+
+
+
+
-
- {currentWeather ? ( - - ) : ( - - )} -
+ + + + + Did you know? +

There are 171, 146 words in the English language!

+ + Search now → + +
+
+
+
+ + + + + + + {favourites.length} + Favourites + + + + + + + + {searchCount} + Searches + + + + +
); -} +}; export default Tab1; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab2.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab2.jsx index 216544f..d3a8909 100644 --- a/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab2.jsx +++ b/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab2.jsx @@ -2,6 +2,7 @@ import { IonButton, IonCol, IonContent, + IonGrid, IonHeader, IonPage, IonRow, @@ -9,30 +10,32 @@ import { IonTitle, IonToolbar, } from '@ionic/react'; -import { useState } from 'react'; -import { CurrentWeather } from '../components/CurrentWeather'; +import { useState, useRef } from 'react'; +import { NoSearch } from '../components/NoSearch'; +import { NoResultsWordCard, WordCard } from '../components/WordCard'; +import { WordStore } from '../store'; +import { searchWord } from '../utils'; -function Tab2() { - const [search, setSearch] = useState(''); - const [currentWeather, setCurrentWeather] = useState(false); +const Tab2 = () => { + const pageRef = useRef(); + const [searchTerm, setSearchTerm] = useState(''); + const [searchResult, setSearchResult] = useState(false); + const [animatedClass, setAnimatedClass] = useState(''); const performSearch = async () => { - getAddress(search); - }; + setAnimatedClass('animate__slideOutRight'); + const result = searchTerm !== '' ? await searchWord(searchTerm) : undefined; - const getAddress = async (city) => { - const response = await fetch( - `https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${city}&aqi=no` - ); - const data = await response.json(); + setTimeout(() => setSearchResult(result === undefined ? 'none' : result), 250); + setTimeout(() => setAnimatedClass('animate__slideInLeft'), 250); - if (data && data.current && data.location) { - setCurrentWeather(data); - } + WordStore.update((s) => { + s.searchCount++; + }); }; return ( - + Search @@ -45,37 +48,36 @@ function Tab2() { - - - setSearch(e.target.value)} - /> - + + + + setSearchTerm(e.target.value)} + /> + - - - Search - - - + + + Search + + + -
- {currentWeather ? ( - - ) : ( -

Your search result will appear here

+ {searchResult && searchResult !== 'none' && ( + )} -
+ + {searchResult && searchResult === 'none' && ( + + )} + + {!searchResult && } +
); -} +}; export default Tab2; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab3.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab3.jsx new file mode 100644 index 0000000..d12efc2 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/AppPages/Tab3.jsx @@ -0,0 +1,45 @@ +import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react'; +import { useStoreState } from 'pullstate'; +import { useRef, useState } from 'react'; +import { NoFavourites } from '../components/NoFavourites'; +import { WordCard } from '../components/WordCard'; +import { WordStore } from '../store'; +import { getFavourites } from '../store/Selectors'; + +const Tab3 = () => { + const pageRef = useRef(); + const favourites = useStoreState(WordStore, getFavourites); + const [animatedClass, setAnimatedClass] = useState('animate__slideInLeft'); + + return ( + + + + Favourites + + + + + + Favourites + + + + {favourites.map((favourite, index) => { + return ( + + ); + })} + + {favourites.length < 1 && } + + + ); +}; + +export default Tab3; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/NoFavourites.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/components/NoFavourites.jsx new file mode 100644 index 0000000..0f446f7 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/components/NoFavourites.jsx @@ -0,0 +1,22 @@ +import { IonCol, IonLabel, IonRow } from '@ionic/react'; + +export const NoFavourites = () => ( + + + +

You don't have any favourites yet!

+

+ Any time you see the heart icon, press it to add the related word to your favourites and + quickly access it from here. +

+ +
+
+
+); diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/NoSearch.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/components/NoSearch.jsx new file mode 100644 index 0000000..27f6fa3 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/components/NoSearch.jsx @@ -0,0 +1,23 @@ +import { IonCol, IonLabel, IonRow } from '@ionic/react'; + +export const NoSearch = () => ( + + + +

Search for a word in the English language

+

+ This app will give you word meaninigs, phonetics, origin and also an audio clip so you can + hear what it sounds like. +

+ +
+
+
+); diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/WordCard.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordCard.jsx new file mode 100644 index 0000000..9ec2346 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordCard.jsx @@ -0,0 +1,129 @@ +import { + IonBadge, + IonButton, + IonCard, + IonCardContent, + IonCardSubtitle, + IonCardTitle, + IonCol, + IonIcon, + IonNote, + IonRow, + useIonModal, +} from '@ionic/react'; +import { checkmarkCircleOutline, chevronForward, closeCircleOutline } from 'ionicons/icons'; +import WordModal from './WordModal'; + +export const WordCard = ({ word, animatedClass, pageRef }) => { + const closeModal = () => { + hideModal(); + }; + + const openModal = () => { + showModal({ + presentingElement: pageRef.current, + onDidDismiss: hideModal, + }); + }; + + const [showModal, hideModal] = useIonModal(WordModal, { + dismiss: closeModal, + word, + }); + + return ( + + + + + {word.word} +
+ {word.meanings && + word.meanings.map((meaning, index) => { + return ( + + {meaning.partOfSpeech} +   + + ); + })} +
+ {word.origin} + + + + {word.meanings.length} + meanings + + + + {word.phonetics.length} + phonetics + + + + + + audio + + + + + + + View  + + + + +
+
+
+
+ ); +}; + +export const NoResultsWordCard = ({ word, animatedClass }) => { + return ( + + + + + Whoops... +
+ no results  + found +
+ + No results have been found for your search criteria! Please try another word. + + + + + 0 + meanings + + + + 0 + phonetics + + + + + + audio + + +
+
+
+
+ ); +}; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/WordCardHeading.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordCardHeading.jsx new file mode 100644 index 0000000..ff23fc0 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordCardHeading.jsx @@ -0,0 +1,10 @@ +import { IonText } from "@ionic/react"; + +export const WordCardHeading = ({ text }) => ( + +
+ +

{ text }

+
+
+); \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/WordMeaning.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordMeaning.jsx new file mode 100644 index 0000000..1f5d3b7 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordMeaning.jsx @@ -0,0 +1,18 @@ +import { IonBadge } from '@ionic/react'; + +export const WordMeaning = ({ meaning, index }) => ( +
0 ? 'ion-padding-top' : ''}> + + {meaning.partOfSpeech} + +
+ {meaning.definitions.map((definition, index2) => { + return ( +

0 ? 'ion-padding-top' : ''}> + {index2 + 1}.  + {definition.definition} +

+ ); + })} +
+); diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/WordModal.jsx b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordModal.jsx new file mode 100644 index 0000000..0896a4b --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/components/WordModal.jsx @@ -0,0 +1,122 @@ +import { + IonBadge, + IonButton, + IonButtons, + IonCard, + IonCardContent, + IonCardHeader, + IonCardSubtitle, + IonCardTitle, + IonCol, + IonContent, + IonGrid, + IonHeader, + IonIcon, + IonNote, + IonPage, + IonRow, + IonText, + IonTitle, + IonToolbar, +} from '@ionic/react'; +import { heart, heartOutline, play } from 'ionicons/icons'; +import { useStoreState } from 'pullstate'; +import { WordStore } from '../store'; +import { getFavourites } from '../store/Selectors'; +import { addToFavourites } from '../store/WordStore'; +import { WordCardHeading } from './WordCardHeading'; +import { WordMeaning } from './WordMeaning'; + +const WordModal = ({ dismiss, word }) => { + const favourites = useStoreState(WordStore, getFavourites); + const isFavourite = favourites.includes(word); + const audio = word.phonetics[0] ? word.phonetics[0].audio : false; + + const playAudio = () => { + const audioElement = new Audio(`https:${audio}`); + audioElement.play(); + }; + + return ( + + + + + addToFavourites(word)}> + + + + View Word + + + Close + + + + + + + + + + {word.word} +
+ {word.meanings && + word.meanings.map((meaning, index) => { + return ( + + + {meaning.partOfSpeech} + +   + + ); + })} +
+ {word.origin} +
+
+
+
+ + {audio && ( + + + + + + + + + + + + + + + + + + )} + + + + + + + + {word.meanings && + word.meanings.map((meaning, index) => { + return ; + })} + + + + +
+
+
+ ); +}; + +export default WordModal; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/index.tsx b/03_source/mobile/src/pages/DemoDictionaryApp/index.tsx index 0cc5228..8e1f78b 100644 --- a/03_source/mobile/src/pages/DemoDictionaryApp/index.tsx +++ b/03_source/mobile/src/pages/DemoDictionaryApp/index.tsx @@ -1,38 +1,44 @@ import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react'; -import { cloudOutline, searchOutline } from 'ionicons/icons'; +import { cloudOutline, heart, search, searchOutline, statsChart } from 'ionicons/icons'; import { Route, Redirect } from 'react-router'; import Tab1 from './AppPages/Tab1'; import Tab2 from './AppPages/Tab2'; +import Tab3 from './AppPages/Tab3'; -function DemoWeatherApp() { +import './style.scss'; + +function DemoDictionaryApp() { return ( - + - + - + - - + + + + {/* */} - - - Dashboard + + - - - Search + + + + + ); } -export default DemoWeatherApp; +export default DemoDictionaryApp; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/store/Selectors.js b/03_source/mobile/src/pages/DemoDictionaryApp/store/Selectors.js new file mode 100644 index 0000000..eeb9eb0 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/store/Selectors.js @@ -0,0 +1,8 @@ +import { createSelector } from 'reselect'; + +const getState = state => state; + +// General getters +export const getFavourites = createSelector(getState, state => state.favourites); +export const getPopularWords = createSelector(getState, state => state.popularWords); +export const getSearchCount = createSelector(getState, state => state.searchCount); \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/store/WordStore.js b/03_source/mobile/src/pages/DemoDictionaryApp/store/WordStore.js new file mode 100644 index 0000000..374c814 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/store/WordStore.js @@ -0,0 +1,29 @@ +import { Store } from "pullstate"; + +const WordStore = new Store({ + + favourites: [], + popularWords: [], + searchCount: 0 +}); + +export default WordStore; + +export const addToFavourites = (passedWord) => { + + const currentFavourites = WordStore.getRawState().favourites; + const added = !currentFavourites.includes(passedWord); + + WordStore.update(s => { + + if (currentFavourites.includes(passedWord)) { + + s.favourites = currentFavourites.filter(word => word !== passedWord); + } else { + + s.favourites = [ ...s.favourites, passedWord ]; + } + }); + + return added; +} \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/store/index.js b/03_source/mobile/src/pages/DemoDictionaryApp/store/index.js new file mode 100644 index 0000000..b232728 --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/store/index.js @@ -0,0 +1 @@ +export { default as WordStore } from "./WordStore"; diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/style.scss b/03_source/mobile/src/pages/DemoDictionaryApp/style.scss index 37c1e1a..bb952e0 100644 --- a/03_source/mobile/src/pages/DemoDictionaryApp/style.scss +++ b/03_source/mobile/src/pages/DemoDictionaryApp/style.scss @@ -1,103 +1,240 @@ -#about-page { - ion-toolbar { - position: absolute; +/* Ionic Variables and Theming. For more info, please see: +http://ionicframework.com/docs/theming/ */ - top: 0; - left: 0; - right: 0; +/** Ionic CSS Variables **/ +.demo-dictionary-app { + * { + /** primary **/ + --ion-color-primary: #953cd0; + --ion-color-primary-rgb: 149, 60, 208; + --ion-color-primary-contrast: #ffffff; + --ion-color-primary-contrast-rgb: 255, 255, 255; + --ion-color-primary-shade: #8335b7; + --ion-color-primary-tint: #a050d5; - --background: transparent; - --color: white; + /** secondary **/ + --ion-color-secondary: #3dc2ff; + --ion-color-secondary-rgb: 61, 194, 255; + --ion-color-secondary-contrast: #ffffff; + --ion-color-secondary-contrast-rgb: 255, 255, 255; + --ion-color-secondary-shade: #36abe0; + --ion-color-secondary-tint: #50c8ff; + + /** tertiary **/ + --ion-color-tertiary: #5260ff; + --ion-color-tertiary-rgb: 82, 96, 255; + --ion-color-tertiary-contrast: #ffffff; + --ion-color-tertiary-contrast-rgb: 255, 255, 255; + --ion-color-tertiary-shade: #4854e0; + --ion-color-tertiary-tint: #6370ff; + + /** success **/ + --ion-color-success: #2dd36f; + --ion-color-success-rgb: 45, 211, 111; + --ion-color-success-contrast: #ffffff; + --ion-color-success-contrast-rgb: 255, 255, 255; + --ion-color-success-shade: #28ba62; + --ion-color-success-tint: #42d77d; + + /** warning **/ + --ion-color-warning: #ffc409; + --ion-color-warning-rgb: 255, 196, 9; + --ion-color-warning-contrast: #000000; + --ion-color-warning-contrast-rgb: 0, 0, 0; + --ion-color-warning-shade: #e0ac08; + --ion-color-warning-tint: #ffca22; + + /** danger **/ + --ion-color-danger: #eb445a; + --ion-color-danger-rgb: 235, 68, 90; + --ion-color-danger-contrast: #ffffff; + --ion-color-danger-contrast-rgb: 255, 255, 255; + --ion-color-danger-shade: #cf3c4f; + --ion-color-danger-tint: #ed576b; + + /** dark **/ + --ion-color-dark: #222428; + --ion-color-dark-rgb: 34, 36, 40; + --ion-color-dark-contrast: #ffffff; + --ion-color-dark-contrast-rgb: 255, 255, 255; + --ion-color-dark-shade: #1e2023; + --ion-color-dark-tint: #383a3e; + + /** medium **/ + --ion-color-medium: #92949c; + --ion-color-medium-rgb: 146, 148, 156; + --ion-color-medium-contrast: #ffffff; + --ion-color-medium-contrast-rgb: 255, 255, 255; + --ion-color-medium-shade: #808289; + --ion-color-medium-tint: #9d9fa6; + + /** light **/ + --ion-color-light: #ffffff; + --ion-color-light-rgb: 255, 255, 255; + --ion-color-light-contrast: #000000; + --ion-color-light-contrast-rgb: 0, 0, 0; + --ion-color-light-shade: #e0e0e0; + --ion-color-light-tint: #ffffff; + + --ion-background-color: #1e1b27 !important; + --ion-tab-bar-color-selected: #953cd0; + --ion-tab-bar-color: #412f6e; + --ion-text-color: white; + --ion-tab-bar-background: #191620; + --ion-toolbar-background: #191620 !important; + --ion-item-background: #000000 !important; + + --ion-card-background: #272333 !important; + --ion-modal-background: #272333 !important; } - ion-toolbar ion-back-button, - ion-toolbar ion-button, - ion-toolbar ion-menu-button { - --color: white; - } - - .about-header { - position: relative; - - width: 100%; - height: 30%; - } - - .about-header .about-image { - position: absolute; - - top: 0; - left: 0; - bottom: 0; - right: 0; - - background-position: center; - background-size: cover; - background-repeat: no-repeat; - - opacity: 0; - - transition: opacity 500ms ease-in-out; - } - - .about-header .madison { - background-image: url('/assets/WeatherDemo/img/about/madison.jpg'); - } - - .about-header .austin { - background-image: url('/assets/WeatherDemo/img/about/austin.jpg'); - } - - .about-header .chicago { - background-image: url('/assets/WeatherDemo/img/about/chicago.jpg'); - } - - .about-header .seattle { - background-image: url('/assets/WeatherDemo/img/about/seattle.jpg'); - } - - .about-info { - position: relative; - margin-top: -10px; - border-radius: 10px; - background: var(--ion-background-color, #fff); - z-index: 2; // display rounded border above header image - } - - .about-info h3 { - margin-top: 0; - } - - .about-info ion-list { - padding-top: 0; - } - - .about-info p { - line-height: 130%; - - color: var(--ion-color-dark); - } - - .about-info ion-icon { - margin-inline-end: 32px; + ion-tab-bar { + --border-style: none; + border: none; } /* - * iOS Only + * Dark Colors + * ------------------------------------------- */ - .ios .about-info { - --ion-padding: 19px; + ion-modal { + -ms-overflow-style: none; /* for Internet Explorer, Edge */ + scrollbar-width: none; /* for Firefox */ + overflow-y: scroll; } - .ios .about-info h3 { - font-weight: 700; + body { + overflow: hidden !important; + --ion-color-primary: #953cd0; + --ion-color-primary-rgb: 149, 60, 208; + --ion-color-primary-contrast: #ffffff; + --ion-color-primary-contrast-rgb: 255, 255, 255; + --ion-color-primary-shade: #8335b7; + --ion-color-primary-tint: #a050d5; + + --ion-color-secondary: #50c8ff; + --ion-color-secondary-rgb: 80, 200, 255; + --ion-color-secondary-contrast: #ffffff; + --ion-color-secondary-contrast-rgb: 255, 255, 255; + --ion-color-secondary-shade: #46b0e0; + --ion-color-secondary-tint: #62ceff; + + --ion-color-tertiary: #6a64ff; + --ion-color-tertiary-rgb: 106, 100, 255; + --ion-color-tertiary-contrast: #ffffff; + --ion-color-tertiary-contrast-rgb: 255, 255, 255; + --ion-color-tertiary-shade: #5d58e0; + --ion-color-tertiary-tint: #7974ff; + + --ion-color-success: #2fdf75; + --ion-color-success-rgb: 47, 223, 117; + --ion-color-success-contrast: #000000; + --ion-color-success-contrast-rgb: 0, 0, 0; + --ion-color-success-shade: #29c467; + --ion-color-success-tint: #44e283; + + --ion-color-warning: #ffd534; + --ion-color-warning-rgb: 255, 213, 52; + --ion-color-warning-contrast: #000000; + --ion-color-warning-contrast-rgb: 0, 0, 0; + --ion-color-warning-shade: #e0bb2e; + --ion-color-warning-tint: #ffd948; + + --ion-color-danger: #ff4961; + --ion-color-danger-rgb: 255, 73, 97; + --ion-color-danger-contrast: #ffffff; + --ion-color-danger-contrast-rgb: 255, 255, 255; + --ion-color-danger-shade: #e04055; + --ion-color-danger-tint: #ff5b71; + + --ion-color-dark: #f4f5f8; + --ion-color-dark-rgb: 244, 245, 248; + --ion-color-dark-contrast: #000000; + --ion-color-dark-contrast-rgb: 0, 0, 0; + --ion-color-dark-shade: #d7d8da; + --ion-color-dark-tint: #f5f6f9; + + --ion-color-medium: #989aa2; + --ion-color-medium-rgb: 152, 154, 162; + --ion-color-medium-contrast: #000000; + --ion-color-medium-contrast-rgb: 0, 0, 0; + --ion-color-medium-shade: #86888f; + --ion-color-medium-tint: #a2a4ab; + + --ion-color-light: #ffffff; + --ion-color-light-rgb: 255, 255, 255; + --ion-color-light-contrast: #000000; + --ion-color-light-contrast-rgb: 0, 0, 0; + --ion-color-light-shade: #e0e0e0; + --ion-color-light-tint: #ffffff; + } + + /* + * iOS Dark Theme + * ------------------------------------------- + */ + + .ios body { + /* --ion-background-color: #000000; */ + /* --ion-background-color-rgb: 0,0,0; */ + + --ion-text-color: #ffffff; + --ion-text-color-rgb: 255, 255, 255; + + --ion-color-step-50: #0d0d0d; + --ion-color-step-100: #1a1a1a; + --ion-color-step-150: #262626; + --ion-color-step-200: #333333; + --ion-color-step-250: #404040; + --ion-color-step-300: #4d4d4d; + --ion-color-step-350: #595959; + --ion-color-step-400: #666666; + --ion-color-step-450: #737373; + --ion-color-step-500: #808080; + --ion-color-step-550: #8c8c8c; + --ion-color-step-600: #999999; + --ion-color-step-650: #a6a6a6; + --ion-color-step-700: #b3b3b3; + --ion-color-step-750: #bfbfbf; + --ion-color-step-800: #cccccc; + --ion-color-step-850: #d9d9d9; + --ion-color-step-900: #e6e6e6; + --ion-color-step-950: #f2f2f2; + } + + /* + * Material Design Dark Theme + * ------------------------------------------- + */ + + .md body { + /* --ion-background-color: #121212; */ + /* --ion-background-color-rgb: 18,18,18; */ + + --ion-text-color: #ffffff; + --ion-text-color-rgb: 255, 255, 255; + + --ion-border-color: #222222; + + --ion-color-step-50: #1e1e1e; + --ion-color-step-100: #2a2a2a; + --ion-color-step-150: #363636; + --ion-color-step-200: #414141; + --ion-color-step-250: #4d4d4d; + --ion-color-step-300: #595959; + --ion-color-step-350: #656565; + --ion-color-step-400: #717171; + --ion-color-step-450: #7d7d7d; + --ion-color-step-500: #898989; + --ion-color-step-550: #949494; + --ion-color-step-600: #a0a0a0; + --ion-color-step-650: #acacac; + --ion-color-step-700: #b8b8b8; + --ion-color-step-750: #c4c4c4; + --ion-color-step-800: #d0d0d0; + --ion-color-step-850: #dbdbdb; + --ion-color-step-900: #e7e7e7; + --ion-color-step-950: #f3f3f3; } } - -#date-input-popover { - --offset-y: -var(--ion-safe-area-bottom); - - --max-width: 90%; - --width: 336px; -} diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/utils.js b/03_source/mobile/src/pages/DemoDictionaryApp/utils.js new file mode 100644 index 0000000..fa5327f --- /dev/null +++ b/03_source/mobile/src/pages/DemoDictionaryApp/utils.js @@ -0,0 +1,21 @@ +import { WordStore } from './store'; + +const API_URL = 'https://api.dictionaryapi.dev/api/v2/entries/en/'; + +export const searchWord = async (word, returnOne = true) => { + const response = await fetch(`${API_URL}${word.toLowerCase()}`); + const data = await response.json(); + + return returnOne ? data[0] : data; +}; + +export const fetchPopularWords = async () => { + const words = ['mobile', 'applications', 'ionic', 'framework']; + + words.forEach(async (word) => { + const wordData = await searchWord(word, false); + WordStore.update((s) => { + s.popularWords = [...s.popularWords, wordData[0]]; + }); + }); +}; diff --git a/03_source/mobile/src/pages/DemoList/index.tsx b/03_source/mobile/src/pages/DemoList/index.tsx index 8274af1..dd90a4e 100644 --- a/03_source/mobile/src/pages/DemoList/index.tsx +++ b/03_source/mobile/src/pages/DemoList/index.tsx @@ -252,6 +252,14 @@ const SettingsPage: React.FC = ({ + + + router.push(paths.DEMO_DICTIONARY_APP, 'forward')}> + + Demo Dictionary App + + + {/* REQ0058/logout */} diff --git a/03_source/mobile/src/pages/WeatherDemo/AppPages/Tab1.jsx b/03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab1.jsx similarity index 100% rename from 03_source/mobile/src/pages/WeatherDemo/AppPages/Tab1.jsx rename to 03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab1.jsx diff --git a/03_source/mobile/src/pages/WeatherDemo/AppPages/Tab2.jsx b/03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab2.jsx similarity index 100% rename from 03_source/mobile/src/pages/WeatherDemo/AppPages/Tab2.jsx rename to 03_source/mobile/src/pages/DemoWeatherApp/AppPages/Tab2.jsx diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/CurrentWeather/WeatherProperty.tsx b/03_source/mobile/src/pages/DemoWeatherApp/components/CurrentWeather/WeatherProperty.tsx similarity index 100% rename from 03_source/mobile/src/pages/DemoDictionaryApp/components/CurrentWeather/WeatherProperty.tsx rename to 03_source/mobile/src/pages/DemoWeatherApp/components/CurrentWeather/WeatherProperty.tsx diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/CurrentWeather/index.tsx b/03_source/mobile/src/pages/DemoWeatherApp/components/CurrentWeather/index.tsx similarity index 100% rename from 03_source/mobile/src/pages/DemoDictionaryApp/components/CurrentWeather/index.tsx rename to 03_source/mobile/src/pages/DemoWeatherApp/components/CurrentWeather/index.tsx diff --git a/03_source/mobile/src/pages/DemoDictionaryApp/components/SkeletonDashboard/index.tsx b/03_source/mobile/src/pages/DemoWeatherApp/components/SkeletonDashboard/index.tsx similarity index 100% rename from 03_source/mobile/src/pages/DemoDictionaryApp/components/SkeletonDashboard/index.tsx rename to 03_source/mobile/src/pages/DemoWeatherApp/components/SkeletonDashboard/index.tsx diff --git a/03_source/mobile/src/pages/WeatherDemo/index.tsx b/03_source/mobile/src/pages/DemoWeatherApp/index.tsx similarity index 100% rename from 03_source/mobile/src/pages/WeatherDemo/index.tsx rename to 03_source/mobile/src/pages/DemoWeatherApp/index.tsx diff --git a/03_source/mobile/src/pages/WeatherDemo/style.scss b/03_source/mobile/src/pages/DemoWeatherApp/style.scss similarity index 100% rename from 03_source/mobile/src/pages/WeatherDemo/style.scss rename to 03_source/mobile/src/pages/DemoWeatherApp/style.scss diff --git a/03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/WeatherProperty.tsx b/03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/WeatherProperty.tsx deleted file mode 100644 index 52949af..0000000 --- a/03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/WeatherProperty.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { IonCardSubtitle, IonCol, IonIcon, IonNote, IonRow } from '@ionic/react'; -import { pulseOutline, sunnyOutline, thermometerOutline } from 'ionicons/icons'; -import { useEffect, useState } from 'react'; - -export const WeatherProperty = ({ type, currentWeather }: { type: any; currentWeather: any }) => { - const [property, setProperty] = useState(false); - - const properties = { - wind: { - isIcon: false, - icon: '/assets/WeatherDemo/wind.png', - alt: 'wind', - label: 'Wind', - value: `${currentWeather.current.wind_mph}mph`, - }, - feelsLike: { - isIcon: true, - icon: thermometerOutline, - alt: 'feels like', - label: 'Feels like', - value: `${currentWeather.current.feelslike_c}°C`, - }, - indexUV: { - isIcon: true, - icon: sunnyOutline, - alt: 'index uv', - label: 'Index UV', - value: currentWeather.current.uv, - }, - pressure: { - isIcon: true, - icon: pulseOutline, - alt: 'pressure', - label: 'Pressure', - value: `${currentWeather.current.pressure_mb} mbar`, - }, - }; - - useEffect(() => { - setProperty(properties[type]); - }, [type]); - - return ( - - - - {!property.isIcon && ( - {property.alt} - )} - {property.isIcon && ( - - )} - - - - {property.label} - {property.value} - - - - ); -}; diff --git a/03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/index.tsx b/03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/index.tsx deleted file mode 100644 index ceb4332..0000000 --- a/03_source/mobile/src/pages/WeatherDemo/components/CurrentWeather/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { IonCard, IonCardContent, IonGrid, IonRow, IonText, IonCardTitle } from '@ionic/react'; -import { WeatherProperty } from './WeatherProperty'; - -export const CurrentWeather = ({ currentWeather }: { currentWeather: any }) => ( - - - - -

- {currentWeather.location.region},{' '} - {currentWeather.location.country} -

-
- -
- condition - - -

{currentWeather.current.condition.text}

-
- - -

{new Date(currentWeather.location.localtime).toDateString()}

-
-
- - - {currentWeather.current.temp_c}℃ - - - - - - - - - - - - - -
-
-
-); diff --git a/03_source/mobile/src/pages/WeatherDemo/components/SkeletonDashboard/index.tsx b/03_source/mobile/src/pages/WeatherDemo/components/SkeletonDashboard/index.tsx deleted file mode 100644 index 234fb9b..0000000 --- a/03_source/mobile/src/pages/WeatherDemo/components/SkeletonDashboard/index.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { - IonCard, - IonCardContent, - IonCardSubtitle, - IonCardTitle, - IonCol, - IonGrid, - IonIcon, - IonNote, - IonRow, - IonSkeletonText, - IonText, - IonThumbnail, -} from '@ionic/react'; -import { pulseOutline, sunnyOutline, thermometerOutline } from 'ionicons/icons'; - -export const SkeletonDashboard = () => ( - - - - -

- -

-
- -
- - - - - -

- -

-
- - -

- -

-
-
- - - - - - - - - - - wind - - - - Wind - - - - - - - - - - - - - - - Feels like - - - - - - - - - - - - - - - - - Index UV - - - - - - - - - - - - - - - Pressure - - - - - - - - -
-
-
-);