Compare commits

..

1 Commits

Author SHA1 Message Date
Torpenn 6343a8bc04
feat: add new UI 2025-04-10 10:01:27 +02:00
7 changed files with 151 additions and 73 deletions

View File

@ -7,7 +7,7 @@ import { formatTime } from '@/components/shared/business/timeHelpers';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { RootStackParamList } from '@/app/RootStackParamList';
import { VerticalSpacer } from '@/components/shared/Spacers';
import { HorizontalSpacer, VerticalSpacer } from '@/components/shared/Spacers';
import { TimerPickerModal } from 'react-native-timer-picker';
import Button from '@/components/shared/Button';
import NumberSelector from '@/components/shared/NumberSelector';
@ -63,14 +63,11 @@ export default function Dashboard() {
return (
<Container>
<Title>{i18n.t('appTitle')}</Title>
<VerticalSpacer heightUnits={8} />
<CardContainer>
<Card backgroundColor="grey" onPress={() => setShowPreparationTimePicker(true)}>
<Card backgroundColor="darkGrey" color="black" borderColor="darkGrey" onPress={() => setShowPreparationTimePicker(true)}>
<CardTextContainer>
<BlackCustomText>{t('preparation')}</BlackCustomText>
<VerticalSpacer heightUnits={3} />
<BlackCustomText>{formatTime(localPreparationTime)}</BlackCustomText>
</CardTextContainer>
</Card>
@ -97,9 +94,10 @@ export default function Dashboard() {
}}
/>
<Card backgroundColor="red" onPress={() => setShowWorkTimePicker(true)}>
<Card backgroundColor="white" borderColor="pink" color="black" onPress={() => setShowWorkTimePicker(true)}>
<CardTextContainer>
<CustomText>{t('fight')}</CustomText>
<VerticalSpacer heightUnits={3} />
<CustomText>{formatTime(localWorkTime)}</CustomText>
</CardTextContainer>
</Card>
@ -126,9 +124,10 @@ export default function Dashboard() {
}}
/>
<Card backgroundColor="green" onPress={() => setShowRestTimePicker(true)}>
<Card backgroundColor="white" borderColor="blue" color='black' onPress={() => setShowRestTimePicker(true)}>
<CardTextContainer>
<CustomText>{t('rest')}</CustomText>
<VerticalSpacer heightUnits={3} />
<CustomText>{formatTime(localRestTime)}</CustomText>
</CardTextContainer>
</Card>
@ -155,28 +154,43 @@ export default function Dashboard() {
}}
/>
<Card backgroundColor="black">
<Card backgroundColor="black" color="white" borderColor="black">
<CardTextContainer>
<CustomText>{t('repetition')}</CustomText>
<WhiteCustomText>{t('repetition')}</WhiteCustomText>
<VerticalSpacer heightUnits={3} />
<NumberSelector reps={localReps} setReps={handleRepsChange} />
</CardTextContainer>
</Card>
</CardContainer>
<VerticalSpacer heightUnits={5} />
<Text>{t('totalTime')}: {totalWorkTime}</Text>
<CenterText>{t('totalTime')}: {totalWorkTime}</CenterText>
<VerticalSpacer heightUnits={5} />
<Button label={t('begin')} onPress={() => navigation.navigate('Timer')} />
<VerticalSpacer heightUnits={5} />
<Button label={t('settings')} onPress={() => navigation.navigate('Settings')} />
<Row>
<SmallButton color="blue" labelColor="white" label={t('settings')} onPress={() => navigation.navigate('Settings')} />
<LargeButton color="pink" labelColor="white" label={t('begin')} onPress={() => navigation.navigate('Timer')} />
</Row>
</Container>
);
}
const Row = styled.View({
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%'
})
const SmallButton = styled(Button)({
width: '30%'
})
const LargeButton = styled(Button)({
width: '65%'
})
const LoadingContainer = styled.View({
flex: 1,
justifyContent: 'center',
@ -196,7 +210,7 @@ const Container = styled.View({
})
const CardTextContainer = styled.View({
flexDirection: 'row',
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'center'
})
@ -207,12 +221,21 @@ const CardContainer = styled.View({
})
const CustomText = styled(Text)(({ theme }) => ({
fontSize: 20,
fontSize: 23,
fontWeight: 'bold',
textAlign: 'center',
}))
const WhiteCustomText = styled(CustomText)(({ theme }) => ({
color: theme.colors.fixed.white
}))
const BlackCustomText = styled(CustomText)(({ theme }) => ({
color: theme.colors.fixed.black
}))
const CenterText = styled(Text)(({ theme }) => ({
textAlign: 'center',
fontSize: 22,
color: theme.colors.fixed.black
}))

View File

@ -189,9 +189,9 @@ export default function Timer() {
const renderBgColor: () => TimerBgColor = () => {
if (isFinish) return "black";
if (isPreparationPhase) return "grey";
if (isWorkPhase) return "red";
if (isWorkPhase) return "pink";
return "green";
return "blue";
};
return (

View File

@ -5,7 +5,7 @@ import styled from '@emotion/native';
import { HorizontalSpacer } from '@/components/shared/Spacers';
import { Text } from '@/components/shared/Themed';
type ButtonColor = 'green' | 'red' | 'grey' | 'white';
type ButtonColor = 'green' | 'red' | 'grey' | 'white' | 'black' | 'darkGrey' | 'blue' | 'pink';
type LabelColor = ButtonColor | 'black';
type IconLocation = 'left' | 'right';
@ -69,11 +69,11 @@ const Container = styled.TouchableOpacity<{
disabled: boolean;
secondary: boolean;
}>(({ theme, bgColor, secondary }) => ({
backgroundColor: theme.colors.fixed[bgColor],
borderWidth: secondary ? 1 : 0,
backgroundColor: secondary ? theme.colors.fixed.white : theme.colors.fixed[bgColor],
borderWidth: 4,
borderColor: theme.colors.fixed[bgColor],
borderRadius: 6,
height: theme.layout.gridUnit * 12,
borderRadius: 0,
height: theme.layout.gridUnit * 20,
justifyContent: 'center',
paddingHorizontal: theme.layout.gridUnit * 4,
alignItems: 'center',

View File

@ -5,30 +5,46 @@ import { TouchableOpacity } from 'react-native';
export interface CardProps {
children: React.ReactNode;
backgroundColor: CardBackgroundColor;
borderColor: CardBorderColor;
color: CardColor;
testID?: string;
onPress?: () => void;
}
type CardBackgroundColor = 'red' | 'green' | 'grey' | 'black';
type CardBackgroundColor = 'red' | 'green' | 'grey' | 'black' | 'white' | 'darkGrey';
type CardBorderColor = 'pink' | 'blue' | 'grey' | 'black' | 'white' | 'darkGrey';
type CardColor = 'black' | 'white';
const Card: React.FC<CardProps> = ({
children,
backgroundColor = 'red',
color = 'black',
borderColor = 'pink',
testID = undefined,
onPress
}) => {
const safeOnPress = useCallback(() => onPress?.(), [onPress]);
const content = (
<Container bgColor={backgroundColor} testID={testID}>
<Container
color={color}
bgColor={backgroundColor}
testID={testID}
borderColor={borderColor}
>
{children}
</Container>
);
const touchableContent = (
<TouchableOpacity onPress={safeOnPress}>
<CustomTouchableOpacity
onPress={safeOnPress}
bgColor={backgroundColor}
color={color}
borderColor={borderColor}
>
{content}
</TouchableOpacity>
</CustomTouchableOpacity>
)
return (
@ -36,14 +52,29 @@ const Card: React.FC<CardProps> = ({
);
};
const Container = styled.View<{
const CustomTouchableOpacity = styled(TouchableOpacity)<{
color: CardColor;
borderColor: CardBorderColor;
bgColor: CardBackgroundColor;
}>(({ theme, bgColor }) => ({
padding: 30,
width: '100%',
borderRadius: 10,
overflow: 'hidden',
}>(({ theme, color, borderColor, bgColor }) => ({
color: theme.colors.fixed[color],
borderColor: theme.colors.fixed[borderColor],
backgroundColor: theme.colors.fixed[bgColor]
}));
const Container = styled.View<{
bgColor: CardBackgroundColor;
borderColor: CardBorderColor;
color: CardColor;
}>(({ theme, bgColor, borderColor, color }) => ({
padding: 25,
width: '100%',
borderRadius: 0,
overflow: 'hidden',
backgroundColor: theme.colors.fixed[bgColor],
borderWidth: 4,
borderColor: theme.colors.fixed[borderColor],
color: theme.colors.fixed[color]
}));
export default Card;

View File

@ -1 +1 @@
export type TimerBgColor = 'red' | 'green' | 'black' | 'grey';
export type TimerBgColor = 'pink' | 'blue' | 'black' | 'grey';

View File

@ -58,56 +58,69 @@ export default function TimerContent({
};
return (
<>
<Title isPreparationPhase={isPreparationPhase}>{getTitle()}</Title>
<View>
<Column bgColor={bgColor}>
<PartContainer>
<Text>3:23</Text>
{!isPreparationPhase && <Reps>{currentRep} / {reps}</Reps>}
{isPreparationPhase && <Reps isPreparationPhase={true}>{t('preparationDescription')}</Reps>}
</PartContainer>
<VerticalSpacer heightUnits={8} />
<PartContainer>
<Title isPreparationPhase={isPreparationPhase}>{getTitle()}</Title>
<VerticalSpacer heightUnits={2} />
<Time isPreparationPhase={isPreparationPhase}>
{formatTime(timeLeft)}
</Time>
</PartContainer>
<Time isPreparationPhase={isPreparationPhase}>
{formatTime(timeLeft)}
</Time>
<PartContainer>
<ButtonContainer bgColor={bgColor}>
<Button
secondary={true}
label={t('prev')}
color={'black'}
labelColor={'white'}
onPress={isPreparationPhase ? handleNoop : previousRep}
status={isPreparationPhase ? 'disabled' : 'ready'}
/>
<VerticalSpacer heightUnits={8} />
<ElasticSpacer />
{!isPreparationPhase && <Reps>{currentRep} / {reps}</Reps>}
{isPreparationPhase && <Reps isPreparationPhase={true}>{t('preparationDescription')}</Reps>}
{isRunning ? (
<Button secondary={true} color={'black'} label={t('stop')} onPress={handleStop} />
) : (
<Button secondary={true} color={'black'} label={t('start')} onPress={handleContinue} />
)}
<VerticalSpacer heightUnits={8} />
<ElasticSpacer />
<ButtonContainer bgColor={bgColor}>
<Button
label={t('prev')}
onPress={isPreparationPhase ? handleNoop : previousRep}
status={isPreparationPhase ? 'disabled' : 'ready'}
/>
<Button
secondary={true}
label={t('next')}
color={'black'}
onPress={isPreparationPhase ? nextRep : nextRep}
status="ready"
/>
</ButtonContainer>
<ElasticSpacer />
<VerticalSpacer heightUnits={4} />
{isRunning ? (
<Button label={t('stop')} onPress={handleStop} />
) : (
<Button label={t('start')} onPress={handleContinue} />
)}
<ElasticSpacer />
<Button
label={t('next')}
onPress={isPreparationPhase ? nextRep : nextRep}
status="ready"
/>
</ButtonContainer>
<VerticalSpacer heightUnits={4} />
<Button label={i18n.t('back')} onPress={handleBackClick} />
</>
<Button label={i18n.t('back')} onPress={handleBackClick} />
</PartContainer>
</Column>
</View>
);
}
const PartContainer = styled(View)({
backgroundColor: 'transparent',
});
const ButtonContainer = styled(View)<{ bgColor: TimerBgColor }>(({ theme, bgColor }) => ({
backgroundColor: theme.colors.fixed[bgColor],
flexDirection: 'row',
gap: 10,
justifyContent: 'space-between',
}));
@ -123,6 +136,13 @@ const Time = styled(Text)<{ isPreparationPhase?: boolean }>(({ theme, isPreparat
color: isPreparationPhase ? theme.colors.fixed.black : theme.colors.fixed.white
}));
const Column = styled(View)<{ bgColor: TimerBgColor }>(({ theme, bgColor }) => ({
flexDirection: 'column',
justifyContent: 'space-around',
height: '100%',
backgroundColor: theme.colors.fixed[bgColor],
}));
const Reps = styled(Text)<{ isPreparationPhase?: boolean }>(({ theme, isPreparationPhase = false }) => ({
fontSize: 30,
fontWeight: 'bold',

View File

@ -3,7 +3,11 @@ const baseColors = {
white: '#FFFFFF',
red: '#FF4141',
green: '#3AC26E',
grey: '#F9F9F9',
grey: '#F5F5F5',
darkGrey: '#D9CFC7',
yellow: '#FFD700',
pink: '#E4007C',
blue: '#86C3E3'
} as const;
export default {