diff --git a/README.md b/README.md
index 6d16ec1..5d6d291 100644
--- a/README.md
+++ b/README.md
@@ -8,4 +8,4 @@ This is a micro-framework for React Native which is designed to help simplify de
# Screenshots
-
+
diff --git a/packages/data/src/out/database_port.ts b/packages/data/src/out/database_port.ts
index fa2d937..0d2f199 100644
--- a/packages/data/src/out/database_port.ts
+++ b/packages/data/src/out/database_port.ts
@@ -4,4 +4,5 @@ export interface DatabasePort {
addUser(params?: { email: string; password: string; token: string }): Promise
fetchUserData(data: UserModel): Promise
fetchUserExists(data: UserModel): Promise
+ removeUser(params: { email: string }): Promise
}
diff --git a/packages/data/src/repositories/user_repository_impl.ts b/packages/data/src/repositories/user_repository_impl.ts
index 421980a..2f7ea5d 100644
--- a/packages/data/src/repositories/user_repository_impl.ts
+++ b/packages/data/src/repositories/user_repository_impl.ts
@@ -14,7 +14,6 @@ export class UserRepositoryImpl implements UserRepository {
async login(params?: { email: string; password: string }): Promise {
const usermodel: any = await this.network.login({ email: params.email, password: params.password })
- console.log(usermodel)
if (usermodel == 'Request failed with status code 403') {
return usermodel
} else {
@@ -31,9 +30,16 @@ export class UserRepositoryImpl implements UserRepository {
email: params.email
})
}
+
async fetchUserExists(params?: { email: string }): Promise {
return await this.database.fetchUserExists({
email: params.email
})
}
+
+ async logout(params?: { email: string }): Promise {
+ return await this.database.removeUser({
+ email: params.email
+ })
+ }
}
diff --git a/packages/database-watermelon/src/dao/user_dao.ts b/packages/database-watermelon/src/dao/user_dao.ts
index bb46b8a..84db18a 100644
--- a/packages/database-watermelon/src/dao/user_dao.ts
+++ b/packages/database-watermelon/src/dao/user_dao.ts
@@ -39,4 +39,14 @@ export class UserDao extends BaseDao {
if (userCount > 0) return true
else return false
}
+
+ async deleteUser(data: { email: string }): Promise {
+ await safeDbCall(
+ this.attachedDatabase.write(async () => {
+ const response: any = await this.databaseData.query(Q.where('email', Q.eq(data.email))).destroyAllPermanently()
+ return response
+ })
+ )
+ return true
+ }
}
diff --git a/packages/database-watermelon/src/database_adapter.ts b/packages/database-watermelon/src/database_adapter.ts
index 96b5679..b8b9ae3 100644
--- a/packages/database-watermelon/src/database_adapter.ts
+++ b/packages/database-watermelon/src/database_adapter.ts
@@ -28,5 +28,10 @@ class DatabaseAdapter implements DatabasePort {
email: data.email
})
}
+ async removeUser(params: { email: string }): Promise {
+ return await this.databases.userDao.deleteUser({
+ email: params.email
+ })
+ }
}
export default DatabaseAdapter
diff --git a/packages/domain/src/di/domain_module.ts b/packages/domain/src/di/domain_module.ts
index 7433dae..023ea43 100644
--- a/packages/domain/src/di/domain_module.ts
+++ b/packages/domain/src/di/domain_module.ts
@@ -2,13 +2,15 @@ import { UserRepository } from './../repository/user_repository'
import { DataModule } from 'data'
import { Graph, ObjectGraph, Provides, Singleton } from 'di'
import { LoginUseCase } from '../usecases/login_user_usecase'
-import { FetchUserDataUseCase, FetchUserExistsUseCase } from '../domain'
+import { LogoutUseCase } from '../usecases/logout_usecase'
+import { FetchUserDataUseCase } from '../usecases/user_details_usecase'
+import { FetchUserExistsUseCase } from '../usecases/user_present_data_usecase'
@Singleton()
@Graph({ subgraphs: [DataModule] })
export class DomainModule extends ObjectGraph {
@Provides()
- providesLoginUseCase(provideUserRepository: UserRepository): LoginUseCase {
+ provideLoginUseCase(provideUserRepository: UserRepository): LoginUseCase {
return new LoginUseCase(provideUserRepository)
}
@Provides()
@@ -19,4 +21,8 @@ export class DomainModule extends ObjectGraph {
provideUserExistsUseCase(provideUserRepository: UserRepository): FetchUserExistsUseCase {
return new FetchUserExistsUseCase(provideUserRepository)
}
+ @Provides()
+ provideLogoutUseCase(provideUserRepository: UserRepository): LogoutUseCase {
+ return new LogoutUseCase(provideUserRepository)
+ }
}
diff --git a/packages/domain/src/domain.ts b/packages/domain/src/domain.ts
index 45c16bd..421e4cd 100644
--- a/packages/domain/src/domain.ts
+++ b/packages/domain/src/domain.ts
@@ -3,6 +3,7 @@ import { FetchUserDataUseCase, FetchUserDataUseCaseParams } from './usecases/use
import { LoginUseCase, LoginParams } from './usecases/login_user_usecase'
import { DomainModule } from './di/domain_module'
import { UserRepository } from './repository/user_repository'
+import { LogoutUseCase, LogoutParams } from './usecases/logout_usecase'
export {
DomainModule,
@@ -12,5 +13,7 @@ export {
FetchUserDataUseCase,
FetchUserDataUseCaseParams,
FetchUserExistsUseCase,
- FetchUserExistsUseCaseParams
+ FetchUserExistsUseCaseParams,
+ LogoutUseCase,
+ LogoutParams
}
diff --git a/packages/domain/src/repository/user_repository.ts b/packages/domain/src/repository/user_repository.ts
index 96a6f6d..0699f8d 100644
--- a/packages/domain/src/repository/user_repository.ts
+++ b/packages/domain/src/repository/user_repository.ts
@@ -4,4 +4,5 @@ export interface UserRepository {
login(params?: { email: string; password: string }): Promise
fetchUserData(params?: { email: string }): Promise
fetchUserExists(params?: { email: string }): Promise
+ logout(params?: { email: string }): Promise
}
diff --git a/packages/domain/src/usecases/logout_usecase.ts b/packages/domain/src/usecases/logout_usecase.ts
new file mode 100644
index 0000000..aa40d8f
--- /dev/null
+++ b/packages/domain/src/usecases/logout_usecase.ts
@@ -0,0 +1,29 @@
+import { UserRepository } from '../repository/user_repository'
+import { FutureUseCase } from './base/base_usecase'
+import { Params } from './base/params'
+
+export class LogoutUseCase extends FutureUseCase {
+ private readonly userRepository: UserRepository
+ constructor(repo: UserRepository) {
+ super()
+ this.userRepository = repo
+ }
+ async execute(params?: LogoutParams): Promise {
+ if (params?.verify()) {
+ return await this.userRepository.logout({
+ email: params.email
+ })
+ } else return false
+ }
+}
+export class LogoutParams extends Params {
+ readonly email?: string
+
+ constructor(params?: { email: string }) {
+ super({})
+ this.email = params.email
+ }
+ verify(): boolean {
+ return true
+ }
+}
diff --git a/packages/localisation/lib/en.json b/packages/localisation/lib/en.json
index 4bdc3cb..e1b5a03 100644
--- a/packages/localisation/lib/en.json
+++ b/packages/localisation/lib/en.json
@@ -11,5 +11,6 @@
"getThere": "Get There.",
"getStarted": "Get Started",
"noInput": "please enter data or a valid data",
- "errorMessage": "please enter proper email and password"
+ "errorMessage": "please enter proper email and password",
+ "logout": "Logout"
}
diff --git a/packages/mobile/App.tsx b/packages/mobile/App.tsx
index f47801b..9885bd1 100644
--- a/packages/mobile/App.tsx
+++ b/packages/mobile/App.tsx
@@ -16,10 +16,6 @@ import SplashScreen from 'react-native-splash-screen'
import { ThemeProvider } from './src/theme/themeprovider'
class App extends Component {
- componentDidMount(): void {
- SplashScreen.hide()
- }
-
render() {
return (
diff --git a/packages/mobile/src/assets/images.ts b/packages/mobile/src/assets/images.ts
index ff2f01a..b8baa03 100644
--- a/packages/mobile/src/assets/images.ts
+++ b/packages/mobile/src/assets/images.ts
@@ -2,6 +2,8 @@ const Images = {
icon: require('./images/logo.png'),
car: require('./images/car.png'),
carBlack: require('./images/carblack.png'),
- iconBlack: require('./images/logoblack.png')
+ iconBlack: require('./images/logoblack.png'),
+ blackLogout: require('./images/blacklogouticon.png'),
+ whiteLogout: require('./images/whitelogouticon.png')
}
export default Images
diff --git a/packages/mobile/src/assets/images/blacklogouticon.png b/packages/mobile/src/assets/images/blacklogouticon.png
new file mode 100644
index 0000000..973a026
Binary files /dev/null and b/packages/mobile/src/assets/images/blacklogouticon.png differ
diff --git a/packages/mobile/src/assets/images/whitelogouticon.png b/packages/mobile/src/assets/images/whitelogouticon.png
new file mode 100644
index 0000000..fb224a5
Binary files /dev/null and b/packages/mobile/src/assets/images/whitelogouticon.png differ
diff --git a/packages/mobile/src/feature/dashboard/dashboard_screen.tsx b/packages/mobile/src/feature/dashboard/dashboard_screen.tsx
index 1143fb9..e35840c 100644
--- a/packages/mobile/src/feature/dashboard/dashboard_screen.tsx
+++ b/packages/mobile/src/feature/dashboard/dashboard_screen.tsx
@@ -6,22 +6,35 @@ import { AppButton } from '../../widgets/app_button/app_button'
import { useTheme } from '../../theme/themeprovider'
import { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
+import { logoutAction } from 'presentation'
+import { useNavigation } from '@react-navigation/native'
+import RoutePaths from '../../navigation/router_path'
import { fetchUserAction } from 'presentation'
const DashboardScreen = () => {
const { theme, isDark } = useTheme()
- const [lodingState, setLodingState] = useState(false)
+ const navigation: any = useNavigation()
const databaseEmail: any = useSelector((state: any) => state?.userData?.data?.payload)
+ const logoutData: any = useSelector((state: any) => state?.logout?.data?.payload)
const dispatch = useDispatch()
useEffect(() => {
dispatch(fetchUserAction({}))
}, [])
+ const onLogoutClick = () => {
+ dispatch(logoutAction({ databaseEmail }))
+ }
return (
+ onLogoutClick()}>
+
+
{`${i18n.t('uber')} - ${databaseEmail}`}
{i18n.t('getThere')}
-
diff --git a/packages/mobile/src/feature/dashboard/dashboard_style.ts b/packages/mobile/src/feature/dashboard/dashboard_style.ts
index 6e36c88..33c1234 100644
--- a/packages/mobile/src/feature/dashboard/dashboard_style.ts
+++ b/packages/mobile/src/feature/dashboard/dashboard_style.ts
@@ -12,9 +12,9 @@ export default StyleSheet.create({
height: '75%'
},
uberText: {
- fontSize: 40,
+ fontSize: 28,
textAlign: 'center',
- marginTop: '15%',
+ marginTop: '10%',
fontFamily: 'Poppins-Regular'
},
getText: {
@@ -33,7 +33,18 @@ export default StyleSheet.create({
height: 350,
alignSelf: 'center',
position: 'absolute',
- bottom: 20,
+ bottom: 30,
right: -100
+ },
+ logoutStyle: {
+ marginTop: 10,
+ width: 30,
+ height: 30,
+ alignSelf: 'flex-end'
+ },
+ logoutButton: {
+ width: 30,
+ height: 30,
+ alignSelf: 'flex-end'
}
})
diff --git a/packages/mobile/src/feature/login/login_screen.tsx b/packages/mobile/src/feature/login/login_screen.tsx
index 6518e3e..0ca50cc 100644
--- a/packages/mobile/src/feature/login/login_screen.tsx
+++ b/packages/mobile/src/feature/login/login_screen.tsx
@@ -33,11 +33,6 @@ const LoginScreen = () => {
else setLodingState(false)
}, [loginData])
- useEffect(() => {
- if (loginData?.status == Status?.success) navigation.navigate(RoutePaths.dashboard)
- else if (loginData?.status == Status?.error) alert(i18n.t('noInput'))
- }, [loginData])
-
return (
@@ -51,9 +46,6 @@ const LoginScreen = () => {
saveData()} />
-
- {i18n.t('forgetPassword')}
-
)
}
diff --git a/packages/mobile/src/feature/login/login_style.ts b/packages/mobile/src/feature/login/login_style.ts
index 80db889..cd3bbd5 100644
--- a/packages/mobile/src/feature/login/login_style.ts
+++ b/packages/mobile/src/feature/login/login_style.ts
@@ -8,7 +8,8 @@ export default StyleSheet.create({
height: Dimensions.get('window').height
},
secView: {
- width: '100%'
+ width: '100%',
+ marginTop: '10%'
},
loginText: {
fontSize: 24,
diff --git a/packages/mobile/src/navigation/app_router.tsx b/packages/mobile/src/navigation/app_router.tsx
index cb6c1d1..e4c477c 100644
--- a/packages/mobile/src/navigation/app_router.tsx
+++ b/packages/mobile/src/navigation/app_router.tsx
@@ -5,15 +5,24 @@ import DashboardScreen from '../feature/dashboard/dashboard_screen'
import LoginScreen from '../feature/login/login_screen'
import RoutePaths from './router_path'
import { useDispatch, useSelector } from 'react-redux'
-import { fetchUserExistsAction } from 'presentation'
+import { Status, fetchUserExistsAction } from 'presentation'
+import SplashScreen from 'react-native-splash-screen'
const AppRouter = () => {
const Stack = createNativeStackNavigator()
- const databaseEmail: any = useSelector((state: any) => state?.userPresentData?.data?.payload)
+ const databaseEmail: any = useSelector((state: any) => state?.userExistsData)
+ const logoutData: any = useSelector((state: any) => state?.logout?.data?.payload)
+
const dispatch = useDispatch()
useEffect(() => {
dispatch(fetchUserExistsAction({}))
}, [])
+
+ useEffect(() => {
+ if (databaseEmail?.status == Status.success) {
+ SplashScreen.hide()
+ }
+ }, [databaseEmail?.status])
return (
{
headerShown: false
}}
>
- {!databaseEmail && }
-
+ {(!databaseEmail?.data?.payload && databaseEmail?.status == Status.success) || logoutData ? (
+
+ ) : (
+
+ )}
)
diff --git a/packages/mobile/src/widgets/app_button/app_button_style.ts b/packages/mobile/src/widgets/app_button/app_button_style.ts
index bfacced..dc97585 100644
--- a/packages/mobile/src/widgets/app_button/app_button_style.ts
+++ b/packages/mobile/src/widgets/app_button/app_button_style.ts
@@ -6,9 +6,9 @@ export default StyleSheet.create({
buttonView: {
alignSelf: 'center',
width: '80%',
+ height: 50,
borderRadius: 15,
- justifyContent: 'center',
- paddingVertical: '5%'
+ justifyContent: 'center'
},
buttonText: {
fontSize: 24,
diff --git a/packages/presentation/src/feature/login/saga.ts b/packages/presentation/src/feature/login/saga.ts
index 42afe60..2f037ab 100644
--- a/packages/presentation/src/feature/login/saga.ts
+++ b/packages/presentation/src/feature/login/saga.ts
@@ -3,17 +3,21 @@ import { Obsidian } from 'di'
import { put } from 'redux-saga/effects'
import { LOGIN } from './actions'
import { LoginParams } from 'domain-layer'
+import { LOGOUT } from '../logout/action'
+import { FETCH_USER_EXISTS } from '../userpresent/action'
function* loginSaga(action) {
const mesage = 'Request failed with status code 403'
try {
const data: any = yield Obsidian.obtain(DomainModule)
- .providesLoginUseCase()
+ .provideLoginUseCase()
.execute(new LoginParams({ email: action?.params?.data?.email, password: action?.params?.data?.password }))
if (data == mesage || data == false) {
yield put({ type: LOGIN.failure, payload: data })
} else {
yield put({ type: LOGIN.success, payload: data })
+ yield put({ type: LOGOUT.failure, payload: false })
+ yield put({ type: FETCH_USER_EXISTS.success, payload: true })
}
} catch (e) {
console.log(e)
diff --git a/packages/presentation/src/feature/logout/action.ts b/packages/presentation/src/feature/logout/action.ts
new file mode 100644
index 0000000..e842691
--- /dev/null
+++ b/packages/presentation/src/feature/logout/action.ts
@@ -0,0 +1,10 @@
+export enum LOGOUT {
+ request = 'LOGOUT_REQUEST',
+ success = 'LOGOUT_SUCCESS',
+ failure = 'LOGOUT_FAILURE'
+}
+
+export const logoutAction = params => ({
+ type: LOGOUT.request,
+ params
+})
diff --git a/packages/presentation/src/feature/logout/reducer.ts b/packages/presentation/src/feature/logout/reducer.ts
new file mode 100644
index 0000000..43b485c
--- /dev/null
+++ b/packages/presentation/src/feature/logout/reducer.ts
@@ -0,0 +1,23 @@
+import data from 'packages/data/lib/data'
+import { Resource } from '../../utils/resource'
+import { LOGOUT } from './action'
+
+const logoutReducer = (initialState = Resource.none, action) => {
+ switch (action.type) {
+ case LOGOUT.request:
+ return Resource.loading()
+
+ case LOGOUT.success:
+ return Resource.success({
+ data: action
+ })
+
+ case LOGOUT.failure:
+ return Resource.error({
+ error: 'User Not logged in'
+ })
+ default:
+ return initialState
+ }
+}
+export default logoutReducer
diff --git a/packages/presentation/src/feature/logout/saga.ts b/packages/presentation/src/feature/logout/saga.ts
new file mode 100644
index 0000000..d8b6a07
--- /dev/null
+++ b/packages/presentation/src/feature/logout/saga.ts
@@ -0,0 +1,22 @@
+import { Obsidian } from 'di'
+import { put } from 'redux-saga/effects'
+import { LogoutParams, DomainModule } from 'domain-layer'
+import { LOGOUT } from './action'
+import { FETCH_USER_EXISTS } from '../userpresent/action'
+
+function* logoutSaga(action) {
+ try {
+ const data: any = yield Obsidian.obtain(DomainModule)
+ .provideLogoutUseCase()
+ .execute(new LogoutParams({ email: action?.params?.databaseEmail }))
+ if (data == false) {
+ yield put({ type: LOGOUT.failure, payload: data })
+ } else {
+ yield put({ type: LOGOUT.success, payload: data })
+ yield put({ type: FETCH_USER_EXISTS.success, payload: false })
+ }
+ } catch (e) {
+ console.log(e)
+ }
+}
+export default logoutSaga
diff --git a/packages/presentation/src/feature/store.ts b/packages/presentation/src/feature/store.ts
index 174afd7..9115963 100644
--- a/packages/presentation/src/feature/store.ts
+++ b/packages/presentation/src/feature/store.ts
@@ -4,13 +4,15 @@ import rootSaga from '../utils/rootSaga'
import loginReducer from './login/reducer'
import fetchUserReducer from './userDetail/reducer'
import fetchUserExistsReducer from './userpresent/reducer'
+import logoutReducer from './logout/reducer'
const sagaMiddleware = createSagaMiddleware()
const store = configureStore({
reducer: combineReducers({
login: loginReducer,
userData: fetchUserReducer,
- userExistsData: fetchUserExistsReducer
+ userExistsData: fetchUserExistsReducer,
+ logout: logoutReducer
}),
middleware: [sagaMiddleware]
})
diff --git a/packages/presentation/src/feature/userDetail/saga.ts b/packages/presentation/src/feature/userDetail/saga.ts
index 8e144b7..c2752ac 100644
--- a/packages/presentation/src/feature/userDetail/saga.ts
+++ b/packages/presentation/src/feature/userDetail/saga.ts
@@ -1,9 +1,8 @@
-import { DomainModule } from 'domain-layer/src/di/domain_module'
+import { DomainModule, FetchUserDataUseCaseParams } from 'domain-layer'
import { Obsidian } from 'di'
import { call, put } from 'redux-saga/effects'
import React from 'react'
import { FETCH_USER_DATA } from './action'
-import { FetchUserDataUseCaseParams } from 'packages/domain/src/domain'
function* fetchUserSaga(action) {
try {
diff --git a/packages/presentation/src/feature/userpresent/saga.ts b/packages/presentation/src/feature/userpresent/saga.ts
index ca26bae..bd0affb 100644
--- a/packages/presentation/src/feature/userpresent/saga.ts
+++ b/packages/presentation/src/feature/userpresent/saga.ts
@@ -1,16 +1,18 @@
-import { DomainModule } from 'domain-layer/src/di/domain_module'
+import { DomainModule, FetchUserExistsUseCaseParams } from 'domain-layer'
import { Obsidian } from 'di'
import { call, put } from 'redux-saga/effects'
import React from 'react'
import { FETCH_USER_EXISTS } from './action'
-import { FetchUserExistsUseCaseParams } from 'packages/domain/src/domain'
+import { LOGOUT } from '../logout/action'
function* fetchUserExistsSaga(action) {
try {
const data = yield Obsidian.obtain(DomainModule)
.provideUserExistsUseCase()
.execute(new FetchUserExistsUseCaseParams({ email: '' }))
+ console.log(data)
yield put({ type: FETCH_USER_EXISTS.success, payload: data })
+ yield put({ type: LOGOUT.success, payload: false })
} catch (e) {
console.log(e)
}
diff --git a/packages/presentation/src/presentation.ts b/packages/presentation/src/presentation.ts
index 5b03721..3654ee2 100644
--- a/packages/presentation/src/presentation.ts
+++ b/packages/presentation/src/presentation.ts
@@ -4,5 +4,6 @@ import { loginAction } from './feature/login/actions'
import { Resource } from './utils/resource'
import store from './feature/store'
import { Status } from './utils/status'
+import { logoutAction } from './feature/logout/action'
-export { store, Status, Resource, loginAction, fetchUserAction, fetchUserExistsAction }
+export { store, Status, Resource, loginAction, fetchUserAction, fetchUserExistsAction, logoutAction }
diff --git a/packages/presentation/src/utils/rootSaga.ts b/packages/presentation/src/utils/rootSaga.ts
index 10fa4ff..d6c90ea 100644
--- a/packages/presentation/src/utils/rootSaga.ts
+++ b/packages/presentation/src/utils/rootSaga.ts
@@ -5,9 +5,12 @@ import { FETCH_USER_DATA } from '../feature/userDetail/action'
import fetchUserSaga from '../feature/userDetail/saga'
import { FETCH_USER_EXISTS } from '../feature/userpresent/action'
import fetchUserExistsSaga from '../feature/userpresent/saga'
+import { LOGOUT } from '../feature/logout/action'
+import logoutSaga from '../feature/logout/saga'
export default function* rootSaga() {
yield takeLatest(LOGIN.request, loginSaga)
yield takeLatest(FETCH_USER_DATA.request, fetchUserSaga)
yield takeLatest(FETCH_USER_EXISTS.request, fetchUserExistsSaga)
+ yield takeLatest(LOGOUT.request, logoutSaga)
}
diff --git a/screenshots/darkTheme.JPEG b/screenshots/darkTheme.JPEG
new file mode 100644
index 0000000..b85be32
Binary files /dev/null and b/screenshots/darkTheme.JPEG differ
diff --git a/screenshots/dash-darktheme.JPEG b/screenshots/dash-darktheme.JPEG
new file mode 100644
index 0000000..db128e2
Binary files /dev/null and b/screenshots/dash-darktheme.JPEG differ
diff --git a/screenshots/dash-lightTheme.JPEG b/screenshots/dash-lightTheme.JPEG
new file mode 100644
index 0000000..04bb07f
Binary files /dev/null and b/screenshots/dash-lightTheme.JPEG differ
diff --git a/screenshots/dashboardscreen.png b/screenshots/dashboardscreen.png
deleted file mode 100644
index 383fe1d..0000000
Binary files a/screenshots/dashboardscreen.png and /dev/null differ
diff --git a/screenshots/lightTheme.JPEG b/screenshots/lightTheme.JPEG
new file mode 100644
index 0000000..bc59a55
Binary files /dev/null and b/screenshots/lightTheme.JPEG differ
diff --git a/screenshots/loginscreen.png b/screenshots/loginscreen.png
deleted file mode 100644
index e3d2d7d..0000000
Binary files a/screenshots/loginscreen.png and /dev/null differ