map
parent
91df8a53bb
commit
486ef51863
|
@ -4,7 +4,7 @@ import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
|||
interface MyIconProps {
|
||||
name: string;
|
||||
size?: number | undefined;
|
||||
color?: number | ColorValue | undefined
|
||||
color?: number | ColorValue | undefined;
|
||||
}
|
||||
|
||||
export function MyIcon({name, size, color}: MyIconProps) {
|
||||
|
|
|
@ -3,6 +3,11 @@ import {Image, ImageProps} from 'react-native';
|
|||
|
||||
type imageType = Blob | undefined;
|
||||
|
||||
export interface BasicImageProp {
|
||||
source: SourceProp;
|
||||
url?: string;
|
||||
data?: imageType;
|
||||
}
|
||||
interface CustomImageProps extends ImageProps {
|
||||
hq?: {source: SourceProp; data: imageType; url: string};
|
||||
}
|
||||
|
@ -11,4 +16,20 @@ function MyImage({...rest}: CustomImageProps) {
|
|||
return <Image {...rest} />;
|
||||
}
|
||||
|
||||
export function getImageURL(
|
||||
image: (BasicImageProp | undefined)[],
|
||||
): string | undefined {
|
||||
for (let i = 0; i < image.length; i++) {
|
||||
const img = image[i];
|
||||
|
||||
if (img === undefined) continue;
|
||||
|
||||
if (img.source === SourceProp.online) {
|
||||
if (img.url !== undefined) return img.url;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export default MyImage;
|
||||
|
|
|
@ -2,12 +2,5 @@ import {Suspense} from 'react';
|
|||
import {Text} from 'react-native';
|
||||
|
||||
export function MySuspenseFallback({children}: {children: React.ReactNode}) {
|
||||
console.log('MySuspenseFallback');
|
||||
|
||||
return (
|
||||
<Suspense
|
||||
fallback={<Text style={{color: 'red', fontSize: 64}}>loading...</Text>}>
|
||||
{children}
|
||||
</Suspense>
|
||||
);
|
||||
return <Suspense fallback={<Text>loading...</Text>}>{children}</Suspense>;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ import {appStatus, non_save_vars} from './appNonSaveVar';
|
|||
import {ThemeTokensType} from '@configs/colors';
|
||||
|
||||
import {chatEntity, roomId} from '@configs/chat/types';
|
||||
import {User} from '@user/types';
|
||||
import {SourceProp, User} from '@user/types';
|
||||
import {AccountName, EventId} from './types';
|
||||
import {PA_Point} from '@components/map/types';
|
||||
import {PAEvent} from '@event/types';
|
||||
import {PAEvent, createEventProp} from '@event/types';
|
||||
|
||||
export const appNonSaveVariablesSlice = createSlice({
|
||||
name: 'non_save_vars',
|
||||
|
@ -31,7 +31,10 @@ export const appNonSaveVariablesSlice = createSlice({
|
|||
removeCachedEvent: (state, action: PayloadAction<EventId>) => {
|
||||
delete state.cachedEvents[action.payload];
|
||||
},
|
||||
|
||||
setJoinedEvent: (state, action: PayloadAction<{id: EventId, isJoined: number}>) => {
|
||||
state.cachedEvents[action.payload.id].isJoined = createEventProp(SourceProp.cached, action.payload.isJoined);
|
||||
},
|
||||
|
||||
setSelectedChat: (state, action: PayloadAction<roomId>) => {
|
||||
state.selectedChat = action.payload;
|
||||
},
|
||||
|
|
|
@ -17,6 +17,8 @@ import {
|
|||
} from './types';
|
||||
|
||||
import {SourceProp} from '@user/types';
|
||||
import { appVarActions } from '@configs/appVarReducer';
|
||||
import { get } from '@gluestack-style/react';
|
||||
|
||||
let cachedEventList: EventID[] = [];
|
||||
|
||||
|
@ -117,6 +119,12 @@ async function getEvent(
|
|||
),
|
||||
lastUpdateTimestamp: eve[eveDBKeys.lastUpdateTimestamp],
|
||||
EventBannerPicture,
|
||||
isJoined: createEventProp(SourceProp.offline, eve[eveDBKeys.isJoined]),
|
||||
minAge: createEventProp(SourceProp.offline, eve[eveDBKeys.minAge]),
|
||||
AddressText: createEventProp(
|
||||
SourceProp.offline,
|
||||
eve[eveDBKeys.AddressText],
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -153,23 +161,10 @@ async function getEvent(
|
|||
|
||||
const resp = {
|
||||
response: {
|
||||
Name: 'test event',
|
||||
Name: 'Bootshaus',
|
||||
Description:
|
||||
'das Event "Tech House Germany" am 08.12.2023 im legendären Bootshaus Köln verspricht eine unvergessliche Nacht voller elektrisierender Beats und pulsierender Rhythmen. Jeder DJ bringt seinen einzigartigen Stil und Energie in das Line-up ein, was eine perfekte Mischung aus klassischem und modernem Tech House garantiert. \n\n' +
|
||||
'Das Bootshaus, bekannt für seine hervorragende Akustik und beeindruckende Lichtshow, bietet die perfekte Kulisse für eine Nacht voller Tanz und Musik. Erleben Sie eine Reise durch die Welt des Tech House, begleitet von den besten Künstlern der Szene. \n\n' +
|
||||
'\n\n\n' +
|
||||
'das Event "Tech House Germany" am 08.12.2023 im legendären Bootshaus Köln verspricht eine unvergessliche Nacht voller elektrisierender Beats und pulsierender Rhythmen. Jeder DJ bringt seinen einzigartigen Stil und Energie in das Line-up ein, was eine perfekte Mischung aus klassischem und modernem Tech House garantiert. \n\n' +
|
||||
'Das Bootshaus, bekannt für seine hervorragende Akustik und beeindruckende Lichtshow, bietet die perfekte Kulisse für eine Nacht voller Tanz und Musik. Erleben Sie eine Reise durch die Welt des Tech House, begleitet von den besten Künstlern der Szene. \n\n' +
|
||||
'\n\n\n' +
|
||||
'das Event "Tech House Germany" am 08.12.2023 im legendären Bootshaus Köln verspricht eine unvergessliche Nacht voller elektrisierender Beats und pulsierender Rhythmen. Jeder DJ bringt seinen einzigartigen Stil und Energie in das Line-up ein, was eine perfekte Mischung aus klassischem und modernem Tech House garantiert. \n\n' +
|
||||
'Das Bootshaus, bekannt für seine hervorragende Akustik und beeindruckende Lichtshow, bietet die perfekte Kulisse für eine Nacht voller Tanz und Musik. Erleben Sie eine Reise durch die Welt des Tech House, begleitet von den besten Künstlern der Szene. \n\n' +
|
||||
'\n\n\n' +
|
||||
'das Event "Tech House Germany" am 08.12.2023 im legendären Bootshaus Köln verspricht eine unvergessliche Nacht voller elektrisierender Beats und pulsierender Rhythmen. Jeder DJ bringt seinen einzigartigen Stil und Energie in das Line-up ein, was eine perfekte Mischung aus klassischem und modernem Tech House garantiert. \n\n' +
|
||||
'Das Bootshaus, bekannt für seine hervorragende Akustik und beeindruckende Lichtshow, bietet die perfekte Kulisse für eine Nacht voller Tanz und Musik. Erleben Sie eine Reise durch die Welt des Tech House, begleitet von den besten Künstlern der Szene. \n\n' +
|
||||
'\n\n\n' +
|
||||
'das Event "Tech House Germany" am 08.12.2023 im legendären Bootshaus Köln verspricht eine unvergessliche Nacht voller elektrisierender Beats und pulsierender Rhythmen. Jeder DJ bringt seinen einzigartigen Stil und Energie in das Line-up ein, was eine perfekte Mischung aus klassischem und modernem Tech House garantiert. \n\n' +
|
||||
'Das Bootshaus, bekannt für seine hervorragende Akustik und beeindruckende Lichtshow, bietet die perfekte Kulisse für eine Nacht voller Tanz und Musik. Erleben Sie eine Reise durch die Welt des Tech House, begleitet von den besten Künstlern der Szene. \n\n' +
|
||||
'\n\n\n' +
|
||||
'Blckbx: \n' +
|
||||
'NIGHTFUNK \n' +
|
||||
'FINIQ \n' +
|
||||
|
@ -183,10 +178,13 @@ async function getEvent(
|
|||
Type: 0,
|
||||
Theme: 0,
|
||||
FriendList: [],
|
||||
UserLength: 5,
|
||||
pic: 'https://www.w3schools.com/w3css/img_lights.jpg',
|
||||
UserLength: 2121,
|
||||
pic: 'https://res.cloudinary.com/coin-nft/image/upload/c_limit,q_auto,w_329/f_auto/v1/cache/1/f2/65/f26573682335fe72b50f0f74041736905308345d6043abbac832856b3a4d2246-ZGMwNDMxZTktYTY4NS00OTQ1LWJiYmUtMDRhY2Q0YzUzMjAy?_a=ATCkFAA0',
|
||||
ButtonAction:
|
||||
'{"url":"https://www.w3schools.com/w3css/img_lights.jpg"}',
|
||||
'{"url":"https://res.cloudinary.com/coin-nft/image/upload/c_limit,q_auto,w_329/f_auto/v1/cache/1/f2/65/f26573682335fe72b50f0f74041736905308345d6043abbac832856b3a4d2246-ZGMwNDMxZTktYTY4NS00OTQ1LWJiYmUtMDRhY2Q0YzUzMjAy?_a=ATCkFAA0"}',
|
||||
|
||||
minAge: 18,
|
||||
AddressText: 'Bootshaus / Auenweg 173 / 51063 Cologne',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -227,6 +225,12 @@ async function getEvent(
|
|||
SourceProp.cached,
|
||||
resp.response.ButtonAction,
|
||||
),
|
||||
minAge: createEventProp(SourceProp.cached, resp.response.minAge),
|
||||
AddressText: createEventProp(
|
||||
SourceProp.cached,
|
||||
resp.response.AddressText,
|
||||
),
|
||||
isJoined: createEventProp(SourceProp.cached, 0),
|
||||
};
|
||||
|
||||
//BigDataManager.setEntry('events', event);
|
||||
|
@ -329,13 +333,48 @@ function initUndefinedEvent(UUID: EventID): PAEvent {
|
|||
hq: createEventProp(SourceProp.online),
|
||||
},
|
||||
ButtonAction: createEventProp(SourceProp.online),
|
||||
isJoined: createEventProp(SourceProp.online),
|
||||
minAge: createEventProp(SourceProp.online),
|
||||
AddressText: createEventProp(SourceProp.online),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
function joinEvent(UUID: EventID): Promise<boolean> {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
store.dispatch(appNonSaveVarActions.setJoinedEvent({id:UUID, isJoined: 1}));
|
||||
|
||||
getEvent(UUID, true).then(() => {
|
||||
resolve(true);
|
||||
}).catch(() => {
|
||||
reject(false);
|
||||
});
|
||||
|
||||
},1000);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function quitEvent(UUID: EventID): Promise<boolean> {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
store.dispatch(appNonSaveVarActions.setJoinedEvent({id:UUID, isJoined: 0}));
|
||||
resolve(true);
|
||||
},1000);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const EventManager = {
|
||||
getEvent,
|
||||
getEventSelector,
|
||||
getEventSelectorPicture,
|
||||
initUndefinedEvent,
|
||||
joinEvent,
|
||||
quitEvent,
|
||||
};
|
||||
export default EventManager;
|
||||
|
|
|
@ -46,9 +46,9 @@ export interface PAEvent {
|
|||
UserLength: BasicEventProp<number>;
|
||||
EventBannerPicture: EventBannerPicture;
|
||||
ButtonAction: BasicEventProp<string>;
|
||||
//isJoined
|
||||
//minAge
|
||||
//AddressText
|
||||
isJoined: BasicEventProp<number>;
|
||||
minAge: BasicEventProp<number>;
|
||||
AddressText: BasicEventProp<string>;
|
||||
}
|
||||
|
||||
export function NumToEventType(num: number): EventType {
|
||||
|
|
|
@ -19,7 +19,7 @@ export const apiPath = {
|
|||
|
||||
export enum apiBackendRequest {
|
||||
LOGIN = '/user/login',
|
||||
APP_START = '/appstart',
|
||||
APP_START = '/user',
|
||||
GET_USER_PROFILE = '/users/:accountName',
|
||||
LOGOUT = '/user/logout',
|
||||
SIGN_UP = '/user/signup',
|
||||
|
@ -29,8 +29,7 @@ export enum apiBackendRequest {
|
|||
REGISTER_STEP_2 = '/verify/email/:xToken/:verifyId',
|
||||
REGISTER_STEP_FINAL = '/admin/users',
|
||||
REGISTER_STEP_FINAL_ACCOUNT_NAME_CHECK = '/admin/users/validation/accountname',
|
||||
LOGIN = '/user',
|
||||
APP_START = '/appstart', */
|
||||
LOGIN = '/user', */
|
||||
}
|
||||
|
||||
type requestGET = {[key: string]: string};
|
||||
|
@ -161,6 +160,8 @@ interface APP_START extends defaultRequest {
|
|||
path: apiBackendRequest.APP_START;
|
||||
|
||||
response: {
|
||||
accountName: AccountName;
|
||||
username: Username;
|
||||
/* TokenValid: boolean;
|
||||
AccountName: AccountName;
|
||||
Username: Username;
|
||||
|
|
|
@ -21,6 +21,9 @@ enum keys {
|
|||
EventBannerPictureBinaryLQ = 'n',
|
||||
EventBannerPictureBinaryHQ = 'o',
|
||||
ButtonAction = 'p',
|
||||
isJoined = 'q',
|
||||
minAge = 'r',
|
||||
AddressText = 's',
|
||||
}
|
||||
|
||||
const name = 'events';
|
||||
|
@ -43,6 +46,9 @@ const propsType: {[key in keyof typeof propsDefault]: string} = {
|
|||
[keys.EventBannerPictureBinaryLQ]: 'data',
|
||||
[keys.EventBannerPictureBinaryHQ]: 'data',
|
||||
[keys.ButtonAction]: 'string',
|
||||
[keys.isJoined]: 'int',
|
||||
[keys.minAge]: 'int',
|
||||
[keys.AddressText]: 'string',
|
||||
};
|
||||
|
||||
const propsDefault = {
|
||||
|
@ -62,6 +68,9 @@ const propsDefault = {
|
|||
[keys.EventBannerPictureBinaryLQ]: new ArrayBuffer(0),
|
||||
[keys.EventBannerPictureBinaryHQ]: new ArrayBuffer(0),
|
||||
[keys.ButtonAction]: '',
|
||||
[keys.isJoined]: 0,
|
||||
[keys.minAge]: 0,
|
||||
[keys.AddressText]: '',
|
||||
};
|
||||
|
||||
const thisSchema: databaseConf<typeof propsDefault, typeof keys> = {
|
||||
|
|
|
@ -6,6 +6,13 @@ interface LangDetails {
|
|||
export default interface LangFormat {
|
||||
details: LangDetails;
|
||||
appName: string;
|
||||
event: {
|
||||
info: string;
|
||||
details: string;
|
||||
tickets: string;
|
||||
join: string;
|
||||
quit: string;
|
||||
};
|
||||
navigation: {
|
||||
home: {
|
||||
profile: {
|
||||
|
|
|
@ -5,6 +5,13 @@ export const lang: LangFormat = {
|
|||
langCode: 'en',
|
||||
langName: 'English',
|
||||
},
|
||||
event: {
|
||||
info: 'INFO',
|
||||
details: 'DETAILS',
|
||||
tickets: 'Tickets',
|
||||
join: 'Join',
|
||||
quit: 'Quit',
|
||||
},
|
||||
appName: 'Party App',
|
||||
navigation: {
|
||||
home: {
|
||||
|
|
|
@ -16,7 +16,7 @@ import ProfileTab, {
|
|||
ProfileStackNavigatorParamList,
|
||||
} from './tabs/main/ProfileTab';
|
||||
import {FadeInView} from '@helper/animations';
|
||||
import {Animated, View} from 'react-native';
|
||||
import {Animated, AppState, View} from 'react-native';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import {
|
||||
RegistrationScreenAnim,
|
||||
|
@ -30,6 +30,7 @@ import {Text} from '@gluestack-ui/themed';
|
|||
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {animated, useSpring} from '@react-spring/native';
|
||||
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||
|
||||
export type RootStackNavigatorParamList = {
|
||||
Home: NavigatorScreenParams<HomeStackNavigatorParamList>;
|
||||
|
@ -43,6 +44,32 @@ export default function Navigation() {
|
|||
const currentUser =
|
||||
reduxStore.getState().appVariables.preferences.selectedAccount;
|
||||
|
||||
useEffect(() => {
|
||||
console.log('APP NAVIGATION');
|
||||
|
||||
makeRequest({
|
||||
path: apiBackendRequest.APP_START,
|
||||
response: {
|
||||
accountName: '',
|
||||
username: '',
|
||||
/*
|
||||
AccountName: '',
|
||||
Description: '',
|
||||
FollowersCount: 0,
|
||||
FollowingCount: 0,
|
||||
Username: '',
|
||||
XpLevel: 0,
|
||||
XpPoints: 0,
|
||||
AvatarUrl: '',
|
||||
AccountStatus: 0,
|
||||
Events: {},
|
||||
TokenValid: false, */
|
||||
},
|
||||
}).then(response => {
|
||||
console.log(response);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Stack.Navigator
|
||||
screenOptions={{
|
||||
|
@ -184,7 +211,7 @@ function CustomTabBar(props: BottomTabBarProps) {
|
|||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
zIndex: 100,
|
||||
position: 'absolute',
|
||||
position: routeName === 'Calendar' ? 'relative' : 'absolute',
|
||||
bottom: 0,
|
||||
borderColor: currentTheme.backgroundDark300,
|
||||
borderWidth: 3,
|
||||
|
|
|
@ -50,7 +50,7 @@ function MapTab() {
|
|||
name="Event"
|
||||
options={{
|
||||
animation: 'slide_from_right',
|
||||
title: 'lang',
|
||||
title: '',
|
||||
headerShown: true,
|
||||
headerStyle: headerStyle,
|
||||
headerShadowVisible: false,
|
||||
|
|
|
@ -32,6 +32,10 @@ const LazyHelp = lazy(() =>
|
|||
import('@pages/profile/help').then(module => ({default: module.Help})),
|
||||
);
|
||||
|
||||
const LazyAbout = lazy(() =>
|
||||
import('@pages/profile/about').then(module => ({default: module.About})),
|
||||
);
|
||||
|
||||
const Help = () => {
|
||||
return (
|
||||
<MySuspenseFallback>
|
||||
|
@ -40,10 +44,6 @@ const Help = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const LazyAbout = lazy(() =>
|
||||
import('@pages/profile/about').then(module => ({default: module.About})),
|
||||
);
|
||||
|
||||
const About = () => {
|
||||
return (
|
||||
<MySuspenseFallback>
|
||||
|
|
|
@ -1,19 +1,58 @@
|
|||
import {MyScreenContainer} from '@components/MyScreenContainer';
|
||||
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
||||
import {Text} from '@gluestack-ui/themed';
|
||||
import {RootState} from '@redux/store';
|
||||
import {Image} from 'react-native';
|
||||
import {FlatList} from 'react-native';
|
||||
import {View} from 'react-native';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
const baseUrls = [
|
||||
'https://www.w3schools.com/w3css/img_lights.jpg',
|
||||
'https://suburbanmen.com/wp-content/uploads/2021/12/instagram-crush-emilia-bte-20211202-125.jpg',
|
||||
'https://i.ytimg.com/vi/X0I6PbIWmPo/hqdefault.jpg',
|
||||
'https://i.ytimg.com/vi/RDrJ1VmRi0w/hqdefault.jpg',
|
||||
];
|
||||
|
||||
const events: ArrayLike<any> | null | undefined = [];
|
||||
|
||||
for (let i = 1; i <= 100; i++) {
|
||||
const randomUrlIndex = Math.floor(Math.random() * baseUrls.length);
|
||||
|
||||
events.push({
|
||||
id: i,
|
||||
url: baseUrls[randomUrlIndex],
|
||||
title: 'Bootshaus',
|
||||
description: '01.12.2023 20:00 Uhr',
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
const events = [
|
||||
{
|
||||
id: 1,
|
||||
url: 'https://www.w3schools.com/w3css/img_lights.jpg',
|
||||
title: 'Bootshaus',
|
||||
description: '01.12.2023 20:00 Uhr',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
url: 'https://suburbanmen.com/wp-content/uploads/2021/12/instagram-crush-emilia-bte-20211202-125.jpg',
|
||||
title: 'Bootshaus',
|
||||
description: '01.12.2023 20:00 Uhr',
|
||||
},
|
||||
];
|
||||
{
|
||||
id: 3,
|
||||
url: 'https://i.ytimg.com/vi/X0I6PbIWmPo/hqdefault.jpg',
|
||||
title: 'Bootshaus',
|
||||
description: '01.12.2023 20:00 Uhr',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
url: 'https://i.ytimg.com/vi/RDrJ1VmRi0w/hqdefault.jpg',
|
||||
title: 'Bootshaus',
|
||||
description: '01.12.2023 20:00 Uhr',
|
||||
},
|
||||
];*/
|
||||
|
||||
export function CalendarScreen() {
|
||||
const currentTheme = useSelector(
|
||||
|
@ -21,8 +60,41 @@ export function CalendarScreen() {
|
|||
);
|
||||
|
||||
return (
|
||||
<MyScreenContainer>
|
||||
<Text>Calendar</Text>
|
||||
</MyScreenContainer>
|
||||
<View>
|
||||
<FlatList
|
||||
data={events}
|
||||
keyExtractor={(item, index) => `${item.id}${index}`}
|
||||
renderItem={({item}) => (
|
||||
<MyTouchableOpacity
|
||||
key={item.id}
|
||||
style={{
|
||||
margin: 12,
|
||||
padding: 12,
|
||||
borderRadius: 10,
|
||||
backgroundColor: currentTheme.backgroundDark300,
|
||||
marginBottom: 12,
|
||||
flexDirection: 'row',
|
||||
gap: 12,
|
||||
}}>
|
||||
<View style={{backgroundColor: currentTheme.backgroundDark200}}>
|
||||
<Image
|
||||
style={{
|
||||
width: 100,
|
||||
height: 60,
|
||||
}}
|
||||
source={{uri: item.url}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<Text size="xl" bold>
|
||||
{item.title}
|
||||
</Text>
|
||||
<Text>{item.description}</Text>
|
||||
</View>
|
||||
</MyTouchableOpacity>
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
import {Center, Spinner, Text, View} from '@gluestack-ui/themed';
|
||||
import {Box, Center, Spinner, Text, View} from '@gluestack-ui/themed';
|
||||
|
||||
import {EventID} from '@event/types';
|
||||
|
||||
import EventManager from '@event/EventManager';
|
||||
import {MyScreenContainer} from '@components/MyScreenContainer';
|
||||
import {SourceProp} from '@user/types';
|
||||
import MyImage from '@components/MyImage';
|
||||
import {Image} from 'react-native';
|
||||
import MyImage, {getImageURL} from '@components/MyImage';
|
||||
import {Image, Linking} from 'react-native';
|
||||
import {useEffect, useState} from 'react';
|
||||
import {useSelector} from 'react-redux';
|
||||
import {RootState} from '@redux/store';
|
||||
import {MyButton} from '@components/MyButton';
|
||||
|
||||
function EventPageLoading() {
|
||||
// center also horizontally and vertically
|
||||
|
@ -17,48 +21,138 @@ function EventPageLoading() {
|
|||
);
|
||||
}
|
||||
|
||||
function EventPage({route}: {route: {params: {eventID: EventID}}}) {
|
||||
function EventPage({
|
||||
route,
|
||||
navigation,
|
||||
}: {
|
||||
route: {params: {eventID: EventID}};
|
||||
navigation: any;
|
||||
}) {
|
||||
const {eventID} = route.params;
|
||||
|
||||
const event = EventManager.getEventSelector(eventID);
|
||||
|
||||
if (event.Name.source === SourceProp.online) return <EventPageLoading />;
|
||||
const lang = useSelector((state: RootState) => state.appVariables.lang.event);
|
||||
|
||||
let image = event.EventBannerPicture.hq;
|
||||
if (image === undefined) {
|
||||
image = event.EventBannerPicture.lq;
|
||||
}
|
||||
|
||||
const imageUrl =
|
||||
'https://res.cloudinary.com/coin-nft/image/upload/c_limit,q_auto,w_329/f_auto/v1/cache/1/f2/65/f26573682335fe72b50f0f74041736905308345d6043abbac832856b3a4d2246-ZGMwNDMxZTktYTY4NS00OTQ1LWJiYmUtMDRhY2Q0YzUzMjAy?_a=ATCkFAA0';
|
||||
const [isJoining, setIsJoining] = useState(false); // for join button (loading)
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch the image dimensions and calculate the aspect ratio
|
||||
Image.getSize(
|
||||
imageUrl,
|
||||
(width, height) => {
|
||||
const calculatedAspectRatio = width / height;
|
||||
setAspectRatio(calculatedAspectRatio);
|
||||
},
|
||||
error => {
|
||||
console.error('Error getting image size: ', error);
|
||||
},
|
||||
);
|
||||
}, [imageUrl]);
|
||||
navigation.setOptions({
|
||||
title: event.Name.data,
|
||||
});
|
||||
}, [event.Name.data]);
|
||||
|
||||
if (event.Name.source === SourceProp.online) return <EventPageLoading />;
|
||||
|
||||
const imageUrl = getImageURL([
|
||||
event.EventBannerPicture.hq,
|
||||
event.EventBannerPicture.lq,
|
||||
]);
|
||||
|
||||
const isJoinedToEvent = event.isJoined.data === 1;
|
||||
|
||||
//const imageUrl = 'https://res.cloudinary.com/coin-nft/image/upload/c_limit,q_auto,w_329/f_auto/v1/cache/1/f2/65/f26573682335fe72b50f0f74041736905308345d6043abbac832856b3a4d2246-ZGMwNDMxZTktYTY4NS00OTQ1LWJiYmUtMDRhY2Q0YzUzMjAy?_a=ATCkFAA0';
|
||||
|
||||
return (
|
||||
<MyScreenContainer scrollView={true}>
|
||||
{
|
||||
<>
|
||||
<Text>{event.Name.data}</Text>
|
||||
<Image
|
||||
source={{
|
||||
uri: imageUrl,
|
||||
}}
|
||||
style={{width: '100%', height: 400}}
|
||||
alt="Event banner"
|
||||
/>
|
||||
<Text>{event.Description.data}</Text>
|
||||
<Box
|
||||
marginBottom={20}
|
||||
style={{
|
||||
maxWidth: '100%',
|
||||
width: 444,
|
||||
}}>
|
||||
<MyImage
|
||||
source={{
|
||||
uri: imageUrl,
|
||||
}}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 250,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
alt="Event banner"
|
||||
/>
|
||||
|
||||
<Text marginTop={10} fontWeight={'100'} color="$textLight400">
|
||||
{lang.info}
|
||||
</Text>
|
||||
<Box
|
||||
padding={10}
|
||||
backgroundColor="$backgroundDark300"
|
||||
borderRadius={10}>
|
||||
<Text>{event.Description.data}</Text>
|
||||
</Box>
|
||||
|
||||
<Text marginTop={10} fontWeight={'100'} color="$textLight400">
|
||||
{lang.details}
|
||||
</Text>
|
||||
<Box
|
||||
padding={10}
|
||||
backgroundColor="$backgroundDark300"
|
||||
borderRadius={10}>
|
||||
<Text color="$textLight400">{event.UserLength.data}</Text>
|
||||
<Text color="$textLight400">{event.minAge.data}</Text>
|
||||
<Text color="$textLight400">{event.AddressText.data}</Text>
|
||||
</Box>
|
||||
|
||||
<MyButton
|
||||
type="secondary"
|
||||
style={{marginTop: 20}}
|
||||
text={lang.tickets}
|
||||
onPress={() => {
|
||||
// open link in browser
|
||||
|
||||
if (event.ButtonAction.data === undefined) return;
|
||||
{
|
||||
const button = JSON.parse(event.ButtonAction.data);
|
||||
|
||||
if (button.url !== undefined) Linking.openURL(button.url);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<MyButton
|
||||
type={isJoinedToEvent ? 'secondary' : 'primary'}
|
||||
style={{marginTop: 5}}
|
||||
isLoading={isJoining}
|
||||
disabled={isJoining}
|
||||
text={isJoinedToEvent ? lang.quit : lang.join}
|
||||
onPress={() => {
|
||||
setIsJoining(true);
|
||||
|
||||
if (!isJoinedToEvent) {
|
||||
EventManager.joinEvent(eventID)
|
||||
.then(() => {
|
||||
setIsJoining(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setIsJoining(false);
|
||||
});
|
||||
} else {
|
||||
EventManager.quitEvent(eventID)
|
||||
.then(() => {
|
||||
setIsJoining(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setIsJoining(false);
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<Text marginTop={10} fontWeight={'100'} color="$textLight400">
|
||||
debug
|
||||
</Text>
|
||||
<Box
|
||||
padding={10}
|
||||
backgroundColor="$backgroundDark300"
|
||||
borderRadius={10}>
|
||||
<Text color="$textLight400">{event.StartDate.data}</Text>
|
||||
<Text color="$textLight400">{event.EndDate.data}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
}
|
||||
</MyScreenContainer>
|
||||
|
|
|
@ -7,11 +7,18 @@ import DisplayMarkerList from '@components/map/DisplayMarkerList';
|
|||
|
||||
import getLocationData from '@components/map/cluster/getData';
|
||||
import {PA_Point} from '@components/map/types';
|
||||
import {store} from '@redux/store';
|
||||
import {RootState, store} from '@redux/store';
|
||||
import {appNonSaveVarActions} from '@configs/appNonSaveVarReducer';
|
||||
import {Position} from '@rnmapbox/maps/src/types/Position';
|
||||
|
||||
import {Dimensions} from 'react-native';
|
||||
import {MyIconButton} from '@components/MyButton';
|
||||
import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
||||
import {MyIcon} from '@components/MyIcon';
|
||||
import {useSelector} from 'react-redux';
|
||||
import {Button, ButtonIcon} from '@gluestack-ui/themed';
|
||||
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
Mapbox.setAccessToken(
|
||||
'pk.eyJ1IjoidGl0YW5pdW1iYWNoIiwiYSI6ImNscGgzZGJxMDAwbHQyaXA2N3BtOWUxbWkifQ.x-f8JJxwQHWmPFI3P6Qn-w',
|
||||
|
@ -25,6 +32,10 @@ export const Map = () => {
|
|||
//const [mapMarkers, setMapMarkers] = useState<PA_Point[]>([]); // Add useState for visibleBounds
|
||||
const [lastDataRerender, setLastDataRerender] = useState(0); // Add useState for visibleBounds
|
||||
|
||||
const colors = useSelector(
|
||||
(state: RootState) => state.nonSaveVariables.theme.colors,
|
||||
);
|
||||
|
||||
const getVisibleBounds = async () => {
|
||||
// return when lastDataRerender is 300ms ago
|
||||
const now = Date.now();
|
||||
|
@ -124,6 +135,14 @@ export const Map = () => {
|
|||
projection="globe">
|
||||
<DisplayMarkerList />
|
||||
</Mapbox.MapView>
|
||||
<MapIconButton
|
||||
MyIconProps={{
|
||||
name: 'close',
|
||||
size: 24,
|
||||
backgroundColor: colors.backgroundDark300,
|
||||
}}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
@ -143,3 +162,30 @@ const styles = StyleSheet.create({
|
|||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
function MapIconButton({
|
||||
onPress,
|
||||
MyIconProps,
|
||||
}: {
|
||||
onPress: () => void;
|
||||
MyIconProps: {
|
||||
name: string;
|
||||
color?: string;
|
||||
size: number;
|
||||
backgroundColor?: string;
|
||||
};
|
||||
}) {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 60,
|
||||
right: 10,
|
||||
|
||||
width: MyIconProps.size * 2,
|
||||
height: MyIconProps.size * 2,
|
||||
}}>
|
||||
<MaterialIcon.Button name="facebook" backgroundColor="#3b5998" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import {MyTouchableOpacity} from '@components/MyTouchableOpacity';
|
|||
import UserManager from '@user/UserManager';
|
||||
import MyUserManager from '@user/MyUserManager';
|
||||
import {apiBackendRequest, makeRequest} from '@helper/request';
|
||||
import reactStringReplace from 'react-string-replace';
|
||||
import {passwordOptions, userNameOptions} from '@configs/types';
|
||||
|
||||
function UserAvatar() {
|
||||
return (
|
||||
|
@ -262,13 +264,22 @@ export function UpdateUsername() {
|
|||
);
|
||||
const navigation = useNavigation<ProfileScreenNavigationProp>();
|
||||
|
||||
// TODO: get username from current logged in user
|
||||
const username = 'Max Mustermann';
|
||||
const user = UserManager.getUserSelector(
|
||||
useSelector(
|
||||
(state: RootState) => state.appVariables.preferences.selectedAccount,
|
||||
),
|
||||
);
|
||||
|
||||
const [newUsername, setNewUsername] = useState(username);
|
||||
const [newUsername, setNewUsername] = useState(user.Username.data || '');
|
||||
|
||||
const info2Text = reactStringReplace(
|
||||
lang.changeUsername.info2,
|
||||
'${minLength}',
|
||||
() => userNameOptions.minLength.toString(),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const changed = username !== newUsername;
|
||||
const changed = user.Username.data !== newUsername;
|
||||
|
||||
navigation.setOptions({
|
||||
headerRight: () =>
|
||||
|
@ -299,7 +310,7 @@ export function UpdateUsername() {
|
|||
<Text color={currentTheme.textLight100} style={{marginTop: 12}}>
|
||||
{lang.changeUsername.info}
|
||||
</Text>
|
||||
<Text color={currentTheme.textLight100}>{lang.changeUsername.info2}</Text>
|
||||
<Text color={currentTheme.textLight100}>{info2Text}</Text>
|
||||
</MyScreenContainer>
|
||||
);
|
||||
}
|
||||
|
@ -318,6 +329,10 @@ export function UpdatePassword() {
|
|||
const [newPassword, setNewPassword] = useState('');
|
||||
const [repeatNewPassword, setRepeatNewPassword] = useState('');
|
||||
|
||||
const infoText = reactStringReplace(lang.info, '${minLength}', () =>
|
||||
passwordOptions.minLength.toString(),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const passwordChanged =
|
||||
currentPassword.length > 0 &&
|
||||
|
@ -375,7 +390,7 @@ export function UpdatePassword() {
|
|||
</View>
|
||||
|
||||
<Text color={currentTheme.textLight100} style={{marginTop: 12}}>
|
||||
{lang.info}
|
||||
{infoText}
|
||||
</Text>
|
||||
<Text color={currentTheme.textLight100}>{lang.info2}</Text>
|
||||
</MyScreenContainer>
|
||||
|
|
|
@ -27,7 +27,7 @@ export function Login() {
|
|||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [accountName, setAccountName] = useState('anna');
|
||||
const [password, setPassword] = useState('testtesttest');
|
||||
const [password, setPassword] = useState('testtesttest1#S');
|
||||
|
||||
const loginEnabled = accountName.length > 0 && password.length > 0;
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ function createNewMyUser(
|
|||
path: apiBackendRequest.APP_START,
|
||||
requestGET: {':AccountName': AccountName},
|
||||
response: {
|
||||
accountName: '',
|
||||
username: '',
|
||||
/*
|
||||
AccountName: '',
|
||||
Description: '',
|
||||
|
|
Reference in New Issue