Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions components/molecules/ProfileHeroCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Text, View } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { useTranslation } from "react-i18next";
import { useAppTheme } from "@/hooks/use-app-theme";

Check failure on line 4 in components/molecules/ProfileHeroCard.tsx

View workflow job for this annotation

GitHub Actions / Lint code

Unable to resolve path to module '@/hooks/use-app-theme'

type ProfileHeroCardProps = {
email?: string | null;
firstname?: string | null;
};

export default function ProfileHeroCard({
email,
firstname,
}: ProfileHeroCardProps) {
const { t } = useTranslation();
const { colors, shadows } = useAppTheme();

return (
<View
className="overflow-hidden rounded-[40px] border px-5 py-5"
style={[
shadows.floating,
{ borderColor: colors.border, backgroundColor: colors.panelSoft },
]}
>
<View className="flex-row items-start justify-between gap-4">
<View className="flex-1">
<View
className="self-start rounded-full px-4 py-2"
style={{ backgroundColor: colors.panelMuted }}
>
<Text
className="font-sans-medium text-[11px] uppercase tracking-[2.4px]"
style={{ color: colors.primary }}
>
{t("profile.title")}
</Text>
</View>

<Text
className="mt-5 font-lora text-[38px] leading-[42px]"
style={{ color: colors.text }}
>
{firstname || "SkinTrack"}
</Text>
<Text
className="mt-2 font-sans text-base"
style={{ color: colors.textMuted }}
>
{email || "skintrack@routine.app"}
</Text>
</View>

<View
className="h-16 w-16 items-center justify-center rounded-full"
style={{ backgroundColor: colors.navIconActiveBackground }}
>
<Ionicons
name="person-outline"
size={28}
color={colors.navIconActive}
/>
</View>
</View>

<View className="mt-6 flex-row gap-3">
<View
className="flex-1 rounded-[28px] px-4 py-4"
style={{ backgroundColor: colors.elevated }}
>
<Text
className="font-sans-medium text-[11px] uppercase tracking-[2px]"
style={{ color: colors.primary }}
>
{t("profile.status")}
</Text>
<Text
className="mt-2 font-sans text-sm leading-6"
style={{ color: colors.textMuted }}
>
{t("profile.statusBody")}
</Text>
</View>

<View
className="flex-1 rounded-[28px] px-4 py-4"
style={{ backgroundColor: colors.panelMuted }}
>
<Text
className="font-sans-medium text-[11px] uppercase tracking-[2px]"
style={{ color: colors.primary }}
>
{t("profile.skinSummary")}
</Text>
<Text
className="mt-2 font-lora text-[28px] leading-8"
style={{ color: colors.text }}
>
78%
</Text>
</View>
</View>
</View>
);
}
61 changes: 61 additions & 0 deletions components/molecules/ProfilePreferenceSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Text, View } from "react-native";
import PreferenceOptionButton from "@/components/atoms/PreferenceOptionButton";

Check failure on line 2 in components/molecules/ProfilePreferenceSelector.tsx

View workflow job for this annotation

GitHub Actions / Lint code

Unable to resolve path to module '@/components/atoms/PreferenceOptionButton'
import { useAppTheme } from "@/hooks/use-app-theme";

Check failure on line 3 in components/molecules/ProfilePreferenceSelector.tsx

View workflow job for this annotation

GitHub Actions / Lint code

Unable to resolve path to module '@/hooks/use-app-theme'

type ProfilePreferenceSelectorProps<T extends string> = {
activeValue: T;
backgroundColor: string;
subtitle: string;
title: string;
options: readonly T[];
optionsGapClassName?: string;
optionClassName?: string;
textClassName: string;
getLabel: (option: T) => string;
onSelect: (option: T) => void;
};

export default function ProfilePreferenceSelector<T extends string>({
activeValue,
backgroundColor,
subtitle,
title,
options,
optionsGapClassName = "gap-3",
optionClassName,
textClassName,
getLabel,
onSelect,
}: ProfilePreferenceSelectorProps<T>) {
const { colors } = useAppTheme();

return (
<View className="rounded-[30px] px-4 py-4" style={{ backgroundColor }}>
<Text
className="font-sans-medium text-[11px] uppercase tracking-[2px]"
style={{ color: colors.primary }}
>
{title}
</Text>
<Text
className="mt-2 font-sans text-sm leading-6"
style={{ color: colors.textMuted }}
>
{subtitle}
</Text>

<View className={`mt-4 flex-row ${optionsGapClassName}`}>
{options.map((option) => (
<PreferenceOptionButton
key={option}
active={activeValue === option}
label={getLabel(option)}
pressableClassName={optionClassName}
textClassName={textClassName}
onPress={() => onSelect(option)}
/>
))}
</View>
</View>
);
}
61 changes: 61 additions & 0 deletions components/molecules/ProfilePreferencesCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { View } from "react-native";
import { useTranslation } from "react-i18next";
import ProfileItem from "@/components/atoms/ProfileItem";
import SectionHeader from "@/components/atoms/SectionHeader";

Check failure on line 4 in components/molecules/ProfilePreferencesCard.tsx

View workflow job for this annotation

GitHub Actions / Lint code

Unable to resolve path to module '@/components/atoms/SectionHeader'
import ProfilePreferenceSelector from "@/components/molecules/ProfilePreferenceSelector";
import { SUPPORTED_LANGUAGES } from "@/i18n/resources";
import type { AppLanguage } from "@/i18n/resources";
import { useAppTheme } from "@/hooks/use-app-theme";

Check failure on line 8 in components/molecules/ProfilePreferencesCard.tsx

View workflow job for this annotation

GitHub Actions / Lint code

Unable to resolve path to module '@/hooks/use-app-theme'
import { setAppLanguage } from "@/services/language";

type ProfilePreferencesCardProps = {
language: AppLanguage | undefined;
};

export default function ProfilePreferencesCard({
language,
}: ProfilePreferencesCardProps) {
const { t } = useTranslation();
const { colors, shadows } = useAppTheme();

return (
<View
className="rounded-[34px] border p-5"
style={[
shadows.card,
{ borderColor: colors.border, backgroundColor: colors.panel },
]}
>
<SectionHeader
eyebrow={t("profile.preferencesEyebrow")}
title={t("profile.preferencesTitle")}
description={t("profile.preferencesSubtitle")}
/>

<View className="gap-4">
<ProfileItem icon="settings-outline" label={t("profile.settings")} />
<ProfileItem
icon="shield-checkmark-outline"
label={t("profile.privacy")}
/>
</View>

<View className="mt-6">
<ProfilePreferenceSelector
activeValue={language ?? "en"}
backgroundColor={colors.panelSoft}
title={t("profile.language.title")}
subtitle={t("profile.language.subtitle")}
options={SUPPORTED_LANGUAGES}
optionClassName="px-4"
optionsGapClassName="gap-3"
textClassName="text-base"
getLabel={(option) => t(`common.languages.${option}`)}
onSelect={(option) => {
void setAppLanguage(option);
}}
/>
</View>
</View>
);
}
29 changes: 29 additions & 0 deletions components/molecules/ProfileSupportCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { View } from "react-native";
import { useTranslation } from "react-i18next";
import ProfileItem from "@/components/atoms/ProfileItem";
import SectionHeader from "@/components/atoms/SectionHeader";

Check failure on line 4 in components/molecules/ProfileSupportCard.tsx

View workflow job for this annotation

GitHub Actions / Lint code

Unable to resolve path to module '@/components/atoms/SectionHeader'
import { useAppTheme } from "@/hooks/use-app-theme";

Check failure on line 5 in components/molecules/ProfileSupportCard.tsx

View workflow job for this annotation

GitHub Actions / Lint code

Unable to resolve path to module '@/hooks/use-app-theme'

export default function ProfileSupportCard() {
const { t } = useTranslation();
const { colors, shadows } = useAppTheme();

return (
<View
className="rounded-[34px] border p-5"
style={[
shadows.card,
{ borderColor: colors.border, backgroundColor: colors.panelMuted },
]}
>
<SectionHeader
eyebrow={t("profile.supportEyebrow")}
title={t("profile.supportTitle")}
description={t("profile.supportSubtitle")}
/>
<View className="gap-4">
<ProfileItem icon="help-circle-outline" label={t("profile.help")} />
</View>
</View>
);
}
Loading