chore: UI and i18n updates — HomeScreen, ProfileScreen, Documents, Generate and locales
This commit is contained in:
3
add-translations.ps1
Normal file
3
add-translations.ps1
Normal file
@@ -0,0 +1,3 @@
|
||||
# Script to add translations - this will be a reference
|
||||
Write-Host 'Adding translations to locale files...'
|
||||
Write-Host 'Files to update: bn, te, gu, kn, ml, mr, pa'
|
||||
@@ -299,6 +299,57 @@ export const bn = {
|
||||
error: 'ত্রুটি',
|
||||
success: 'সফলতা',
|
||||
|
||||
// Documents Screen
|
||||
documentsScreen: {
|
||||
title: 'নথি',
|
||||
subtitle: 'AI-চালিত নথি ব্যবস্থাপনা',
|
||||
overview: 'সারসংক্ষেপ',
|
||||
recentActivity: 'সাম্প্রতিক কার্যকলাপ',
|
||||
quickActions: 'দ্রুত কাজ',
|
||||
activities: {
|
||||
invoiceUploaded: 'ইনভয়েস #2024-089 আপলোড করা হয়েছে',
|
||||
contractSigned: 'চুক্তি স্বাক্ষরিত ও সংরক্ষিত',
|
||||
legalUpdated: 'আইনি নথি আপডেট করা হয়েছে',
|
||||
hoursAgo: '{{hours}} ঘন্টা আগে',
|
||||
yesterday: 'গতকাল',
|
||||
daysAgo: '{{days}} দিন আগে',
|
||||
},
|
||||
actions: {
|
||||
searchDocuments: 'নথি খুঁজুন',
|
||||
searchDescription: 'যেকোনো নথি তাৎক্ষণিক খুঁজে পান',
|
||||
bulkUpload: 'বাল্ক আপলোড',
|
||||
bulkUploadDescription: 'একসাথে একাধিক ফাইল আপলোড করুন',
|
||||
},
|
||||
},
|
||||
|
||||
// Generate Screen
|
||||
generateScreen: {
|
||||
title: 'তৈরি করুন',
|
||||
subtitle: 'AI-চালিত বিষয়বস্তু তৈরি',
|
||||
seasonalCampaigns: 'মৌসুমী প্রচারাভিযান',
|
||||
contentTemplates: 'বিষয়বস্তু টেমপ্লেট',
|
||||
customization: 'কাস্টমাইজেশন',
|
||||
templates: {
|
||||
blogPost: 'ব্লগ পোস্ট',
|
||||
blogPostDescription: 'SEO-অপ্টিমাইজড ব্লগ কনটেন্ট তৈরি করুন',
|
||||
emailCampaign: 'ইমেল প্রচারাভিযান',
|
||||
emailCampaignDescription: 'আকর্ষণীয় ইমেল নিউজলেটার তৈরি করুন',
|
||||
socialMedia: 'সোশ্যাল মিডিয়া',
|
||||
socialMediaDescription: 'সকল প্ল্যাটফর্মের জন্য পোস্ট তৈরি করুন',
|
||||
designAssets: 'ডিজাইন সম্পদ',
|
||||
designAssetsDescription: 'ব্র্যান্ডেড ভিজ্যুয়াল তৈরি করুন',
|
||||
},
|
||||
brandVoiceDescription: 'আপনার অনন্য ব্র্যান্ড টোন সংজ্ঞায়িত করুন',
|
||||
},
|
||||
|
||||
// Profile Screen
|
||||
profileScreen: {
|
||||
profileSettings: 'প্রোফাইল ও সেটিংস',
|
||||
generateContent: 'বিষয়বস্তু তৈরি করুন',
|
||||
more: 'আরও',
|
||||
signOut: 'সাইন আউট',
|
||||
},
|
||||
|
||||
tasksScreen: {
|
||||
tabs: {
|
||||
hr: 'মানব সম্পদ',
|
||||
|
||||
@@ -337,6 +337,57 @@ export const en = {
|
||||
subtitle: 'Choose your preferred language to localise the experience.',
|
||||
},
|
||||
|
||||
// Documents Screen
|
||||
documentsScreen: {
|
||||
title: 'Documents',
|
||||
subtitle: 'AI-powered document management',
|
||||
overview: 'Overview',
|
||||
recentActivity: 'Recent Activity',
|
||||
quickActions: 'Quick Actions',
|
||||
activities: {
|
||||
invoiceUploaded: 'Invoice #2024-089 uploaded',
|
||||
contractSigned: 'Contract signed & archived',
|
||||
legalUpdated: 'Legal doc updated',
|
||||
hoursAgo: '{{hours}} hours ago',
|
||||
yesterday: 'Yesterday',
|
||||
daysAgo: '{{days}} days ago',
|
||||
},
|
||||
actions: {
|
||||
searchDocuments: 'Search Documents',
|
||||
searchDescription: 'Find any document instantly',
|
||||
bulkUpload: 'Bulk Upload',
|
||||
bulkUploadDescription: 'Upload multiple files at once',
|
||||
},
|
||||
},
|
||||
|
||||
// Generate Screen
|
||||
generateScreen: {
|
||||
title: 'Generate',
|
||||
subtitle: 'AI-powered content creation',
|
||||
seasonalCampaigns: 'Seasonal Campaigns',
|
||||
contentTemplates: 'Content Templates',
|
||||
customization: 'Customization',
|
||||
templates: {
|
||||
blogPost: 'Blog Post',
|
||||
blogPostDescription: 'Generate SEO-optimized blog content',
|
||||
emailCampaign: 'Email Campaign',
|
||||
emailCampaignDescription: 'Create engaging email newsletters',
|
||||
socialMedia: 'Social Media',
|
||||
socialMediaDescription: 'Craft posts for all platforms',
|
||||
designAssets: 'Design Assets',
|
||||
designAssetsDescription: 'Generate branded visuals',
|
||||
},
|
||||
brandVoiceDescription: 'Define your unique brand tone',
|
||||
},
|
||||
|
||||
// Profile Screen
|
||||
profileScreen: {
|
||||
profileSettings: 'Profile & Settings',
|
||||
generateContent: 'Generate Content',
|
||||
more: 'More',
|
||||
signOut: 'Sign Out',
|
||||
},
|
||||
|
||||
// Tasks Screen
|
||||
tasksScreen: {
|
||||
tabs: {
|
||||
|
||||
@@ -337,6 +337,57 @@ export const hi = {
|
||||
subtitle: 'अपनी पसंदीदा भाषा चुनें ताकि अनुभव स्थानीय हो सके।',
|
||||
},
|
||||
|
||||
// Documents Screen
|
||||
documentsScreen: {
|
||||
title: 'दस्तावेज़',
|
||||
subtitle: 'AI-संचालित दस्तावेज़ प्रबंधन',
|
||||
overview: 'अवलोकन',
|
||||
recentActivity: 'हाल की गतिविधि',
|
||||
quickActions: 'त्वरित कार्य',
|
||||
activities: {
|
||||
invoiceUploaded: 'चालान #2024-089 अपलोड किया गया',
|
||||
contractSigned: 'अनुबंध हस्ताक्षरित और संग्रहीत',
|
||||
legalUpdated: 'कानूनी दस्तावेज़ अपडेट किया गया',
|
||||
hoursAgo: '{{hours}} घंटे पहले',
|
||||
yesterday: 'कल',
|
||||
daysAgo: '{{days}} दिन पहले',
|
||||
},
|
||||
actions: {
|
||||
searchDocuments: 'दस्तावेज़ खोजें',
|
||||
searchDescription: 'किसी भी दस्तावेज़ को तुरंत खोजें',
|
||||
bulkUpload: 'बल्क अपलोड',
|
||||
bulkUploadDescription: 'एक साथ कई फाइलें अपलोड करें',
|
||||
},
|
||||
},
|
||||
|
||||
// Generate Screen
|
||||
generateScreen: {
|
||||
title: 'उत्पन्न करें',
|
||||
subtitle: 'AI-संचालित सामग्री निर्माण',
|
||||
seasonalCampaigns: 'मौसमी अभियान',
|
||||
contentTemplates: 'सामग्री टेम्पलेट',
|
||||
customization: 'अनुकूलन',
|
||||
templates: {
|
||||
blogPost: 'ब्लॉग पोस्ट',
|
||||
blogPostDescription: 'SEO-अनुकूलित ब्लॉग सामग्री उत्पन्न करें',
|
||||
emailCampaign: 'ईमेल अभियान',
|
||||
emailCampaignDescription: 'आकर्षक ईमेल न्यूज़लेटर बनाएं',
|
||||
socialMedia: 'सोशल मीडिया',
|
||||
socialMediaDescription: 'सभी प्लेटफ़ॉर्म के लिए पोस्ट तैयार करें',
|
||||
designAssets: 'डिज़ाइन संपत्ति',
|
||||
designAssetsDescription: 'ब्रांडेड विज़ुअल उत्पन्न करें',
|
||||
},
|
||||
brandVoiceDescription: 'अपना अनूठा ब्रांड टोन परिभाषित करें',
|
||||
},
|
||||
|
||||
// Profile Screen
|
||||
profileScreen: {
|
||||
profileSettings: 'प्रोफ़ाइल और सेटिंग्स',
|
||||
generateContent: 'सामग्री उत्पन्न करें',
|
||||
more: 'अधिक',
|
||||
signOut: 'साइन आउट',
|
||||
},
|
||||
|
||||
// Tasks Screen
|
||||
tasksScreen: {
|
||||
tabs: {
|
||||
|
||||
@@ -299,6 +299,57 @@ export const ta = {
|
||||
subtitle: 'அனுபவத்தை உள்ளூர்மயமாக்க உங்கள் விருப்ப மொழியைத் தேர்வு செய்யவும்.',
|
||||
},
|
||||
|
||||
// Documents Screen
|
||||
documentsScreen: {
|
||||
title: 'ஆவணங்கள்',
|
||||
subtitle: 'AI-இயக்கப்படும் ஆவண மேலாண்மை',
|
||||
overview: 'கண்ணோட்டம்',
|
||||
recentActivity: 'சமீபத்திய செயல்பாடு',
|
||||
quickActions: 'விரைவு செயல்கள்',
|
||||
activities: {
|
||||
invoiceUploaded: 'விலைப்பட்டியல் #2024-089 பதிவேற்றப்பட்டது',
|
||||
contractSigned: 'ஒப்பந்தம் கையெழுத்திடப்பட்டது & காப்பகப்படுத்தப்பட்டது',
|
||||
legalUpdated: 'சட்ட ஆவணம் புதுப்பிக்கப்பட்டது',
|
||||
hoursAgo: '{{hours}} மணி நேரம் முன்பு',
|
||||
yesterday: 'நேற்று',
|
||||
daysAgo: '{{days}} நாட்களுக்கு முன்பு',
|
||||
},
|
||||
actions: {
|
||||
searchDocuments: 'ஆவணங்களைத் தேடு',
|
||||
searchDescription: 'எந்த ஆவணத்தையும் உடனடியாக கண்டறியவும்',
|
||||
bulkUpload: 'மொத்த பதிவேற்றம்',
|
||||
bulkUploadDescription: 'ஒரே நேரத்தில் பல கோப்புகளை பதிவேற்றவும்',
|
||||
},
|
||||
},
|
||||
|
||||
// Generate Screen
|
||||
generateScreen: {
|
||||
title: 'உருவாக்கு',
|
||||
subtitle: 'AI-இயக்கப்படும் உள்ளடக்க உருவாக்கம்',
|
||||
seasonalCampaigns: 'பருவகால பிரச்சாரங்கள்',
|
||||
contentTemplates: 'உள்ளடக்க வார்ப்புருக்கள்',
|
||||
customization: 'தனிப்பயனாக்கம்',
|
||||
templates: {
|
||||
blogPost: 'வலைப்பதிவு இடுகை',
|
||||
blogPostDescription: 'SEO-உகந்த வலைப்பதிவு உள்ளடக்கத்தை உருவாக்கவும்',
|
||||
emailCampaign: 'மின்னஞ்சல் பிரச்சாரம்',
|
||||
emailCampaignDescription: 'ஈர்க்கும் மின்னஞ்சல் செய்திமடல்களை உருவாக்கவும்',
|
||||
socialMedia: 'சமூக ஊடகம்',
|
||||
socialMediaDescription: 'அனைத்து தளங்களுக்கும் இடுகைகளை உருவாக்கவும்',
|
||||
designAssets: 'வடிவமைப்பு சொத்துக்கள்',
|
||||
designAssetsDescription: 'பிராண்ட் காட்சிப்படுத்தல்களை உருவாக்கவும்',
|
||||
},
|
||||
brandVoiceDescription: 'உங்கள் தனித்துவமான பிராண்ட் குரலை வரையறுக்கவும்',
|
||||
},
|
||||
|
||||
// Profile Screen
|
||||
profileScreen: {
|
||||
profileSettings: 'சுயவிவரம் & அமைப்புகள்',
|
||||
generateContent: 'உள்ளடக்கத்தை உருவாக்கு',
|
||||
more: 'மேலும்',
|
||||
signOut: 'வெளியேறு',
|
||||
},
|
||||
|
||||
tasksScreen: {
|
||||
tabs: {
|
||||
hr: 'மனிதவள',
|
||||
|
||||
@@ -1,81 +1,276 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import React, { useMemo } from 'react';
|
||||
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { colors } from '../theme/colors';
|
||||
import { AgentCard } from '../components/AgentCard';
|
||||
import { colors, typography, spacing, borderRadius, shadows, iconSizes } from '../theme';
|
||||
|
||||
type Agent = {
|
||||
id: string;
|
||||
name: string;
|
||||
role: string;
|
||||
avatar: string;
|
||||
status: 'active' | 'idle' | 'busy';
|
||||
};
|
||||
|
||||
const agentConfigs: Array<{
|
||||
id: string;
|
||||
avatar: string;
|
||||
status: Agent['status'];
|
||||
nameKey: string;
|
||||
roleKey: string;
|
||||
}> = [
|
||||
{
|
||||
id: 'evelyn',
|
||||
avatar: 'https://i.pravatar.cc/120?img=1',
|
||||
status: 'active',
|
||||
nameKey: 'evelyn',
|
||||
roleKey: 'agentsScreen.roles.accountant',
|
||||
},
|
||||
{
|
||||
id: 'malik',
|
||||
avatar: 'https://i.pravatar.cc/120?img=2',
|
||||
status: 'active',
|
||||
nameKey: 'malik',
|
||||
roleKey: 'agentsScreen.roles.hrManager',
|
||||
},
|
||||
{
|
||||
id: 'aria',
|
||||
avatar: 'https://i.pravatar.cc/120?img=3',
|
||||
status: 'idle',
|
||||
nameKey: 'aria',
|
||||
roleKey: 'agentsScreen.roles.adminAssistant',
|
||||
},
|
||||
{
|
||||
id: 'marcus',
|
||||
avatar: 'https://i.pravatar.cc/120?img=4',
|
||||
status: 'active',
|
||||
nameKey: 'agentsScreen.names.marcus',
|
||||
roleKey: 'agentsScreen.roles.strategyAdvisor',
|
||||
},
|
||||
{
|
||||
id: 'sofia',
|
||||
avatar: 'https://i.pravatar.cc/120?img=5',
|
||||
status: 'busy',
|
||||
nameKey: 'agentsScreen.names.sofia',
|
||||
roleKey: 'agentsScreen.roles.crmSpecialist',
|
||||
},
|
||||
{
|
||||
id: 'alex',
|
||||
avatar: 'https://i.pravatar.cc/120?img=6',
|
||||
status: 'idle',
|
||||
nameKey: 'agentsScreen.names.alex',
|
||||
roleKey: 'agentsScreen.roles.contentDesigner',
|
||||
},
|
||||
];
|
||||
|
||||
export const AgentsScreen: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const agents: Agent[] = useMemo(
|
||||
() =>
|
||||
agentConfigs.map((config) => ({
|
||||
id: config.id,
|
||||
avatar: config.avatar,
|
||||
status: config.status,
|
||||
name: t(config.nameKey),
|
||||
role: t(config.roleKey),
|
||||
})),
|
||||
[t]
|
||||
);
|
||||
|
||||
const statusSummary = useMemo(
|
||||
() => [
|
||||
{
|
||||
color: '#4ADE80',
|
||||
label: t('agentsScreen.statusSummary.active', { count: 3 }),
|
||||
},
|
||||
{
|
||||
color: '#FBBF24',
|
||||
label: t('agentsScreen.statusSummary.idle', { count: 2 }),
|
||||
},
|
||||
{
|
||||
color: '#F87171',
|
||||
label: t('agentsScreen.statusSummary.busy', { count: 1 }),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
const quickActions = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: 'message-text',
|
||||
label: t('agentsScreen.actions.chat'),
|
||||
},
|
||||
{
|
||||
icon: 'history',
|
||||
label: t('agentsScreen.actions.reports'),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<View style={styles.headerRow}>
|
||||
<Text style={styles.title}>{t('aiAgents')}</Text>
|
||||
<View style={styles.header}>
|
||||
<View>
|
||||
<Text style={styles.title}>{t('agentsScreen.title')}</Text>
|
||||
<Text style={styles.subtitle}>{t('agentsScreen.subtitle')}</Text>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={styles.addButton}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t('agentsScreen.actions.addAgent')}
|
||||
>
|
||||
<MaterialCommunityIcons name="plus" size={iconSizes.md} color={colors.background} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<SectionCard title={t('campaignArchitect')} description={t('pipelineOrchestrator')}>
|
||||
<View style={styles.agentCard}>
|
||||
<View style={styles.statusPill}>
|
||||
<Text style={styles.statusLabel}>{t('transcodingDataFeeds')}</Text>
|
||||
</View>
|
||||
<Text style={styles.agentSummary}>
|
||||
{t('agentSummary')}
|
||||
</Text>
|
||||
</View>
|
||||
</SectionCard>
|
||||
{/* Active Agents Stats */}
|
||||
<View style={styles.statsCard}>
|
||||
{statusSummary.map((item, index) => (
|
||||
<React.Fragment key={item.label}>
|
||||
{index > 0 && <View style={styles.statDivider} />}
|
||||
<View style={styles.statItem}>
|
||||
<View style={[styles.statDot, { backgroundColor: item.color }]} />
|
||||
<Text style={styles.statLabel}>{item.label}</Text>
|
||||
</View>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<View style={styles.actionsList}>
|
||||
<ListButton label={t('transcoved')} />
|
||||
<ListButton label={t('invoices')} />
|
||||
<ListButton label={t('reports')} />
|
||||
{/* Agents Grid */}
|
||||
<View style={styles.sectionHeader}>
|
||||
<Text style={styles.sectionTitle}>{t('agentsScreen.availableTitle')}</Text>
|
||||
<Text style={styles.sectionSubtitle}>{t('agentsScreen.availableSubtitle')}</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.agentsGrid}>
|
||||
{agents.map((agent) => (
|
||||
<AgentCard
|
||||
key={agent.id}
|
||||
name={agent.name}
|
||||
role={agent.role}
|
||||
avatar={agent.avatar}
|
||||
status={agent.status}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<View style={styles.quickActions}>
|
||||
<Text style={styles.sectionTitle}>{t('agentsScreen.quickActionsTitle')}</Text>
|
||||
<View style={styles.actionsGrid}>
|
||||
{quickActions.map((action) => (
|
||||
<TouchableOpacity key={action.label} style={styles.actionButton}>
|
||||
<MaterialCommunityIcons name={action.icon} size={iconSizes.lg} color={colors.highlight} />
|
||||
<Text style={styles.actionLabel}>{action.label}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
headerRow: {
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
alignItems: 'flex-start',
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
title: {
|
||||
fontSize: 32,
|
||||
fontWeight: '900',
|
||||
...typography.h1,
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.8,
|
||||
},
|
||||
agentCard: {
|
||||
gap: 16,
|
||||
},
|
||||
statusPill: {
|
||||
alignSelf: 'flex-start',
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 20,
|
||||
backgroundColor: 'rgba(14, 95, 79, 0.9)',
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 6 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 10,
|
||||
elevation: 6,
|
||||
},
|
||||
statusLabel: {
|
||||
fontSize: 13,
|
||||
fontWeight: '700',
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.4,
|
||||
},
|
||||
agentSummary: {
|
||||
fontSize: 14,
|
||||
subtitle: {
|
||||
...typography.body,
|
||||
color: colors.textSecondary,
|
||||
lineHeight: 22,
|
||||
marginTop: spacing.xs,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
addButton: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: borderRadius.md,
|
||||
backgroundColor: colors.highlight,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
...shadows.glow,
|
||||
},
|
||||
statsCard: {
|
||||
flexDirection: 'row',
|
||||
padding: spacing.lg,
|
||||
borderRadius: borderRadius.lg,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
marginBottom: spacing.lg,
|
||||
...shadows.md,
|
||||
},
|
||||
statItem: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: spacing.sm,
|
||||
},
|
||||
statDot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
},
|
||||
statLabel: {
|
||||
...typography.bodyBold,
|
||||
color: colors.textPrimary,
|
||||
},
|
||||
statDivider: {
|
||||
width: 1,
|
||||
height: '100%',
|
||||
backgroundColor: colors.border,
|
||||
},
|
||||
sectionHeader: {
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
sectionTitle: {
|
||||
...typography.h3,
|
||||
color: colors.highlightAlt,
|
||||
},
|
||||
sectionSubtitle: {
|
||||
...typography.caption,
|
||||
color: colors.textSecondary,
|
||||
marginTop: 4,
|
||||
},
|
||||
agentsGrid: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: spacing.md,
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
quickActions: {
|
||||
marginTop: spacing.lg,
|
||||
},
|
||||
actionsGrid: {
|
||||
flexDirection: 'row',
|
||||
gap: spacing.md,
|
||||
marginTop: spacing.lg,
|
||||
},
|
||||
actionButton: {
|
||||
flex: 1,
|
||||
padding: spacing.lg,
|
||||
borderRadius: borderRadius.lg,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
alignItems: 'center',
|
||||
gap: spacing.sm,
|
||||
...shadows.md,
|
||||
},
|
||||
actionLabel: {
|
||||
...typography.caption,
|
||||
color: colors.textPrimary,
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,50 +1 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { TasksStackParamList } from '../types/navigation';
|
||||
import { TaskHeader } from '../components/TaskHeader';
|
||||
import { colors } from '../theme/colors';
|
||||
|
||||
type Props = NativeStackScreenProps<TasksStackParamList, 'CRM'>;
|
||||
|
||||
export const CRMScreen: React.FC<Props> = ({ navigation }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<TaskHeader
|
||||
title={t('crm')}
|
||||
caption={t('signalStudio')}
|
||||
active="CRM"
|
||||
onNavigate={screen => navigation.navigate(screen)}
|
||||
/>
|
||||
|
||||
<SectionCard title={t('aiMisceles')} description={t('leadsMonitor')}>
|
||||
<Text style={styles.cardBody}>
|
||||
{t('pipelineExposure')}
|
||||
</Text>
|
||||
</SectionCard>
|
||||
|
||||
<View style={styles.actionsList}>
|
||||
<ListButton label={t('aiInsights')} />
|
||||
<ListButton label={t('recommendations')} />
|
||||
<ListButton label={t('playbooks')} />
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
cardBody: {
|
||||
fontSize: 14,
|
||||
color: colors.textSecondary,
|
||||
lineHeight: 22,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
},
|
||||
});
|
||||
export { TasksScreen as CRMScreen } from './TasksScreen';
|
||||
|
||||
@@ -1,45 +1,212 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { colors } from '../theme/colors';
|
||||
import { QuickActionCard } from '../components/QuickActionCard';
|
||||
import { StatCard } from '../components/StatCard';
|
||||
import { colors, spacing, borderRadius, typography, shadows, iconSizes } from '../theme';
|
||||
|
||||
type DocumentCategory = {
|
||||
id: string;
|
||||
icon: string;
|
||||
label: string;
|
||||
count: number;
|
||||
color?: string;
|
||||
};
|
||||
|
||||
export const DocumentsScreen: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const documentCategories: DocumentCategory[] = [
|
||||
{ id: 'invoices', icon: 'file-document', label: t('invoices'), count: 24 },
|
||||
{ id: 'contracts', icon: 'file-sign', label: t('contracts'), count: 8, color: '#4ADE80' },
|
||||
{ id: 'legal', icon: 'scale-balance', label: t('legal'), count: 12, color: '#F59E0B' },
|
||||
{ id: 'hr', icon: 'account-tie', label: t('hr'), count: 16, color: '#3B82F6' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<View style={styles.headerRow}>
|
||||
<Text style={styles.title}>{t('documents')}</Text>
|
||||
<Screen showBackground={true}>
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<View>
|
||||
<Text style={styles.title}>{t('documentsScreen.title')}</Text>
|
||||
<Text style={styles.subtitle}>{t('documentsScreen.subtitle')}</Text>
|
||||
</View>
|
||||
<TouchableOpacity style={styles.addButton}>
|
||||
<MaterialCommunityIcons name="plus" size={iconSizes.md} color={colors.background} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<SectionCard title={t('newDocument')} description={t('autoPrepped')}>
|
||||
<View style={styles.actionsList}>
|
||||
<ListButton label={t('invoices')} />
|
||||
<ListButton label={t('contracts')} />
|
||||
<ListButton label={t('legal')} />
|
||||
<ListButton label={t('hr')} />
|
||||
{/* Stats Overview */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionLabel}>{t('documentsScreen.overview')}</Text>
|
||||
<View style={styles.statsGrid}>
|
||||
{documentCategories.map((category) => (
|
||||
<StatCard
|
||||
key={category.id}
|
||||
icon={category.icon}
|
||||
label={category.label}
|
||||
value={category.count.toString()}
|
||||
color={category.color}
|
||||
style={styles.statCard}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</SectionCard>
|
||||
</View>
|
||||
|
||||
{/* Recent Activity */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionLabel}>{t('documentsScreen.recentActivity')}</Text>
|
||||
<View style={styles.activityCard}>
|
||||
<View style={styles.activityItem}>
|
||||
<View style={styles.activityIcon}>
|
||||
<MaterialCommunityIcons name="file-upload" size={iconSizes.md} color={colors.highlight} />
|
||||
</View>
|
||||
<View style={styles.activityContent}>
|
||||
<Text style={styles.activityTitle}>{t('documentsScreen.activities.invoiceUploaded')}</Text>
|
||||
<Text style={styles.activityTime}>{t('documentsScreen.activities.hoursAgo', { hours: 2 })}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.activityDivider} />
|
||||
<View style={styles.activityItem}>
|
||||
<View style={styles.activityIcon}>
|
||||
<MaterialCommunityIcons name="file-check" size={iconSizes.md} color="#4ADE80" />
|
||||
</View>
|
||||
<View style={styles.activityContent}>
|
||||
<Text style={styles.activityTitle}>{t('documentsScreen.activities.contractSigned')}</Text>
|
||||
<Text style={styles.activityTime}>{t('documentsScreen.activities.yesterday')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.activityDivider} />
|
||||
<View style={styles.activityItem}>
|
||||
<View style={styles.activityIcon}>
|
||||
<MaterialCommunityIcons name="file-document-edit" size={iconSizes.md} color="#F59E0B" />
|
||||
</View>
|
||||
<View style={styles.activityContent}>
|
||||
<Text style={styles.activityTitle}>{t('documentsScreen.activities.legalUpdated')}</Text>
|
||||
<Text style={styles.activityTime}>{t('documentsScreen.activities.daysAgo', { days: 3 })}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionLabel}>{t('documentsScreen.quickActions')}</Text>
|
||||
<View style={styles.actionsContainer}>
|
||||
<QuickActionCard
|
||||
icon="file-plus"
|
||||
label={t('newDocument')}
|
||||
description={t('autoPrepped')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
<QuickActionCard
|
||||
icon="magnify"
|
||||
label={t('documentsScreen.actions.searchDocuments')}
|
||||
description={t('documentsScreen.actions.searchDescription')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
<QuickActionCard
|
||||
icon="cloud-upload"
|
||||
label={t('documentsScreen.actions.bulkUpload')}
|
||||
description={t('documentsScreen.actions.bulkUploadDescription')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
headerRow: {
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
alignItems: 'flex-start',
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
title: {
|
||||
fontSize: 32,
|
||||
fontWeight: '900',
|
||||
...typography.h1,
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.8,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
subtitle: {
|
||||
...typography.body,
|
||||
color: colors.textSecondary,
|
||||
marginTop: spacing.xs,
|
||||
},
|
||||
addButton: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: borderRadius.md,
|
||||
backgroundColor: colors.highlight,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
...shadows.glow,
|
||||
},
|
||||
section: {
|
||||
marginBottom: spacing.xl,
|
||||
},
|
||||
sectionLabel: {
|
||||
...typography.caption,
|
||||
fontSize: 11,
|
||||
fontWeight: '800',
|
||||
color: colors.textSecondary,
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 1.2,
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
statsGrid: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: spacing.md,
|
||||
},
|
||||
statCard: {
|
||||
flex: 1,
|
||||
minWidth: 150,
|
||||
},
|
||||
activityCard: {
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderRadius: borderRadius.lg,
|
||||
padding: spacing.lg,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
...shadows.md,
|
||||
},
|
||||
activityItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: spacing.md,
|
||||
},
|
||||
activityIcon: {
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: borderRadius.md,
|
||||
backgroundColor: colors.surface,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
activityContent: {
|
||||
flex: 1,
|
||||
gap: spacing.xs,
|
||||
},
|
||||
activityTitle: {
|
||||
...typography.bodyBold,
|
||||
fontSize: 15,
|
||||
color: colors.textPrimary,
|
||||
},
|
||||
activityTime: {
|
||||
...typography.caption,
|
||||
color: colors.textSecondary,
|
||||
},
|
||||
activityDivider: {
|
||||
height: 1,
|
||||
backgroundColor: colors.border,
|
||||
marginVertical: spacing.md,
|
||||
},
|
||||
actionsContainer: {
|
||||
gap: spacing.md,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,85 +1,158 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { colors } from '../theme/colors';
|
||||
import { QuickActionCard } from '../components/QuickActionCard';
|
||||
import { colors, spacing, borderRadius, typography, shadows, iconSizes } from '../theme';
|
||||
|
||||
export const GenerateScreen: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const campaigns = [
|
||||
{ key: 'festivities', label: t('festivities') },
|
||||
{ key: 'diwali', label: t('diwali') },
|
||||
{ key: 'newYear', label: t('newYear') }
|
||||
{ key: 'festivities', label: t('festivities'), icon: 'party-popper' },
|
||||
{ key: 'diwali', label: t('diwali'), icon: 'candle' },
|
||||
{ key: 'newYear', label: t('newYear'), icon: 'firework' }
|
||||
];
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<View style={styles.headerRow}>
|
||||
<Text style={styles.title}>{t('generate')}</Text>
|
||||
<Screen showBackground={true}>
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<View>
|
||||
<Text style={styles.title}>{t('generateScreen.title')}</Text>
|
||||
<Text style={styles.subtitle}>{t('generateScreen.subtitle')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<SectionCard title={t('seasonalKits')} description={t('aiGenerated')}>
|
||||
<View style={styles.chipList}>
|
||||
{/* Seasonal Campaigns */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionLabel}>{t('generateScreen.seasonalCampaigns')}</Text>
|
||||
<View style={styles.campaignGrid}>
|
||||
{campaigns.map(item => (
|
||||
<View key={item.key} style={styles.chip}>
|
||||
<Text style={styles.chipLabel}>{item.label}</Text>
|
||||
<Text style={styles.chipCaption}>{t('campaignBlueprint')}</Text>
|
||||
</View>
|
||||
<TouchableOpacity key={item.key} style={styles.campaignCard}>
|
||||
<View style={styles.campaignIcon}>
|
||||
<MaterialCommunityIcons name={item.icon} size={iconSizes.xl} color={colors.highlight} />
|
||||
</View>
|
||||
<View style={styles.campaignContent}>
|
||||
<Text style={styles.campaignLabel}>{item.label}</Text>
|
||||
<Text style={styles.campaignCaption}>{t('campaignBlueprint')}</Text>
|
||||
</View>
|
||||
<MaterialCommunityIcons name="chevron-right" size={iconSizes.md} color={colors.textSecondary} />
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</SectionCard>
|
||||
</View>
|
||||
|
||||
<View style={styles.actionsList}>
|
||||
<ListButton label={t('aiGenerated')} />
|
||||
<ListButton label={t('brandVoice')} />
|
||||
{/* Content Templates */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionLabel}>{t('generateScreen.contentTemplates')}</Text>
|
||||
<View style={styles.actionsContainer}>
|
||||
<QuickActionCard
|
||||
icon="file-document-edit"
|
||||
label={t('generateScreen.templates.blogPost')}
|
||||
description={t('generateScreen.templates.blogPostDescription')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
<QuickActionCard
|
||||
icon="email-newsletter"
|
||||
label={t('generateScreen.templates.emailCampaign')}
|
||||
description={t('generateScreen.templates.emailCampaignDescription')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
<QuickActionCard
|
||||
icon="post"
|
||||
label={t('generateScreen.templates.socialMedia')}
|
||||
description={t('generateScreen.templates.socialMediaDescription')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Brand Voice */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionLabel}>{t('generateScreen.customization')}</Text>
|
||||
<View style={styles.actionsContainer}>
|
||||
<QuickActionCard
|
||||
icon="microphone"
|
||||
label={t('brandVoice')}
|
||||
description={t('generateScreen.brandVoiceDescription')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
<QuickActionCard
|
||||
icon="palette"
|
||||
label={t('generateScreen.templates.designAssets')}
|
||||
description={t('generateScreen.templates.designAssetsDescription')}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
headerRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
header: {
|
||||
marginBottom: spacing.xl,
|
||||
},
|
||||
title: {
|
||||
fontSize: 32,
|
||||
fontWeight: '900',
|
||||
...typography.h1,
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.8,
|
||||
},
|
||||
chipList: {
|
||||
gap: 16,
|
||||
subtitle: {
|
||||
...typography.body,
|
||||
color: colors.textSecondary,
|
||||
marginTop: spacing.xs,
|
||||
},
|
||||
chip: {
|
||||
padding: 20,
|
||||
borderRadius: 20,
|
||||
backgroundColor: 'rgba(26, 64, 54, 0.92)',
|
||||
section: {
|
||||
marginBottom: spacing.xl,
|
||||
},
|
||||
sectionLabel: {
|
||||
...typography.caption,
|
||||
fontSize: 11,
|
||||
fontWeight: '800',
|
||||
color: colors.textSecondary,
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 1.2,
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
campaignGrid: {
|
||||
gap: spacing.md,
|
||||
},
|
||||
campaignCard: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
padding: spacing.lg,
|
||||
borderRadius: borderRadius.lg,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
gap: spacing.md,
|
||||
...shadows.md,
|
||||
},
|
||||
campaignIcon: {
|
||||
width: 52,
|
||||
height: 52,
|
||||
borderRadius: borderRadius.md,
|
||||
backgroundColor: colors.surface,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 12 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 16,
|
||||
elevation: 10,
|
||||
gap: 8,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
chipLabel: {
|
||||
fontSize: 17,
|
||||
fontWeight: '800',
|
||||
campaignContent: {
|
||||
flex: 1,
|
||||
gap: spacing.xs,
|
||||
},
|
||||
campaignLabel: {
|
||||
...typography.h4,
|
||||
fontSize: 16,
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.4,
|
||||
},
|
||||
chipCaption: {
|
||||
fontSize: 13,
|
||||
campaignCaption: {
|
||||
...typography.caption,
|
||||
color: colors.textSecondary,
|
||||
fontWeight: '600',
|
||||
letterSpacing: 0.2,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
actionsContainer: {
|
||||
gap: spacing.md,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,50 +1 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { colors } from '../theme/colors';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import { TaskHeader } from '../components/TaskHeader';
|
||||
import { TasksStackParamList } from '../types/navigation';
|
||||
|
||||
type Props = NativeStackScreenProps<TasksStackParamList, 'HR'>;
|
||||
|
||||
export const HRScreen: React.FC<Props> = ({ navigation }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<TaskHeader
|
||||
title={t('hr')}
|
||||
caption={t('peoplePulse')}
|
||||
onNavigate={screen => navigation.navigate(screen)}
|
||||
active="HR"
|
||||
/>
|
||||
|
||||
<SectionCard title={t('engagement')} description={t('aiBrief')}>
|
||||
<Text style={styles.cardBody}>
|
||||
{t('cultureIntelligence')}
|
||||
</Text>
|
||||
</SectionCard>
|
||||
|
||||
<View style={styles.actionsList}>
|
||||
<ListButton label={t('employees')} />
|
||||
<ListButton label={t('attendance')} />
|
||||
<ListButton label={t('invoices')} />
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
cardBody: {
|
||||
fontSize: 14,
|
||||
color: colors.textSecondary,
|
||||
lineHeight: 22,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
},
|
||||
});
|
||||
export { TasksScreen as HRScreen } from './TasksScreen';
|
||||
|
||||
@@ -1,87 +1,295 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Image, StyleSheet, Text, View, ImageBackground, TouchableOpacity } from 'react-native';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { Image, StyleSheet, Text, View, TouchableOpacity, ScrollView, Modal } from 'react-native';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import type { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { SummaryCard } from '../components/SummaryCard';
|
||||
import { StatCard } from '../components/StatCard';
|
||||
import { QuickActionCard } from '../components/QuickActionCard';
|
||||
import { LanguageSelector } from '../components/LanguageSelector';
|
||||
import { colors } from '../theme/colors';
|
||||
import { colors, typography, spacing, borderRadius, shadows } from '../theme';
|
||||
import type { MainTabParamList } from '../types/navigation';
|
||||
|
||||
type Avatar = {
|
||||
const logo = require('../assets/ic_launcher_foreground.png');
|
||||
|
||||
type NavigationProp = BottomTabNavigationProp<MainTabParamList, 'Home'>;
|
||||
|
||||
interface Company {
|
||||
id: string;
|
||||
name: string;
|
||||
role: string;
|
||||
};
|
||||
industry: string;
|
||||
revenue: string;
|
||||
employees: number;
|
||||
growth: string;
|
||||
invoicesPending: number;
|
||||
hrApprovals: number;
|
||||
renewalDays: number;
|
||||
}
|
||||
|
||||
const avatars: Avatar[] = [
|
||||
{ name: 'Evelyn', role: 'Accountant' },
|
||||
{ name: 'Malik', role: 'HR' },
|
||||
{ name: 'Aria', role: 'Admin' },
|
||||
const COMPANIES: Company[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'TechCorp Solutions',
|
||||
industry: 'Technology',
|
||||
revenue: '₹1.2M',
|
||||
employees: 45,
|
||||
growth: '+18%',
|
||||
invoicesPending: 5,
|
||||
hrApprovals: 3,
|
||||
renewalDays: 7,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Green Retail Pvt Ltd',
|
||||
industry: 'Retail',
|
||||
revenue: '₹850K',
|
||||
employees: 28,
|
||||
growth: '+12%',
|
||||
invoicesPending: 8,
|
||||
hrApprovals: 2,
|
||||
renewalDays: 14,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Skyline Manufacturing',
|
||||
industry: 'Manufacturing',
|
||||
revenue: '₹2.5M',
|
||||
employees: 120,
|
||||
growth: '+25%',
|
||||
invoicesPending: 12,
|
||||
hrApprovals: 7,
|
||||
renewalDays: 3,
|
||||
},
|
||||
];
|
||||
|
||||
const ActionItem: React.FC<{ icon: string; label: string }> = ({ icon, label }) => (
|
||||
<View style={styles.actionItem}>
|
||||
<MaterialCommunityIcons name={icon} size={24} color={colors.highlight} />
|
||||
<Text style={styles.actionLabel}>{label}</Text>
|
||||
<MaterialCommunityIcons name="chevron-right" size={24} color={colors.highlight} />
|
||||
</View>
|
||||
);
|
||||
|
||||
export const HomeScreen: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigation = useNavigation<NavigationProp>();
|
||||
const [languageSelectorVisible, setLanguageSelectorVisible] = useState(false);
|
||||
const [companyDropdownVisible, setCompanyDropdownVisible] = useState(false);
|
||||
const [selectedCompany, setSelectedCompany] = useState<Company>(COMPANIES[0]);
|
||||
|
||||
// User name from profile - this can be made dynamic later
|
||||
const userName = t('johnDoe'); // John Doe
|
||||
|
||||
const greeting = useMemo(() => {
|
||||
return `Hi, ${userName}`;
|
||||
}, [userName]);
|
||||
|
||||
const summaryItems = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: 'file-document-outline',
|
||||
count: selectedCompany.invoicesPending,
|
||||
label: t('homeScreen.summary.invoicesPending', { count: selectedCompany.invoicesPending }),
|
||||
color: colors.highlight,
|
||||
},
|
||||
{
|
||||
icon: 'account-check',
|
||||
count: selectedCompany.hrApprovals,
|
||||
label: t('homeScreen.summary.hrApprovals', { count: selectedCompany.hrApprovals }),
|
||||
color: '#4ADE80',
|
||||
},
|
||||
{
|
||||
icon: 'refresh',
|
||||
count: 1,
|
||||
label: `Renewal in ${selectedCompany.renewalDays} days`,
|
||||
color: '#FBBF24',
|
||||
},
|
||||
],
|
||||
[t, selectedCompany]
|
||||
);
|
||||
|
||||
const statItems = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: 'cash',
|
||||
label: t('homeScreen.stats.revenue'),
|
||||
value: selectedCompany.revenue,
|
||||
trend: { value: selectedCompany.growth, isPositive: true },
|
||||
},
|
||||
{
|
||||
icon: 'account-group',
|
||||
label: t('homeScreen.stats.employees'),
|
||||
value: selectedCompany.employees.toString(),
|
||||
trend: { value: '+2', isPositive: true },
|
||||
},
|
||||
{
|
||||
icon: 'chart-line',
|
||||
label: t('homeScreen.stats.growth'),
|
||||
value: selectedCompany.growth,
|
||||
trend: { value: '+5%', isPositive: true },
|
||||
},
|
||||
],
|
||||
[t, selectedCompany]
|
||||
);
|
||||
|
||||
const quickActions = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: 'email-send',
|
||||
label: t('homeScreen.actions.sendSalarySlips.label'),
|
||||
description: t('homeScreen.actions.sendSalarySlips.description', { count: 15 }),
|
||||
badge: 15,
|
||||
color: undefined,
|
||||
},
|
||||
{
|
||||
icon: 'file-refresh',
|
||||
label: t('homeScreen.actions.renewVendorContract.label'),
|
||||
description: t('homeScreen.actions.renewVendorContract.description', { days: 5 }),
|
||||
badge: '!',
|
||||
color: '#FBBF24',
|
||||
},
|
||||
{
|
||||
icon: 'chart-box',
|
||||
label: t('homeScreen.actions.reviewPnLReport.label'),
|
||||
description: t('homeScreen.actions.reviewPnLReport.description'),
|
||||
badge: undefined,
|
||||
color: undefined,
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
<Screen showBackground={true}>
|
||||
<View style={styles.headerRow}>
|
||||
<Text style={styles.title}>{t('home')}</Text>
|
||||
<View style={styles.headerRight}>
|
||||
{/* Top Bar */}
|
||||
<View style={styles.topBar}>
|
||||
<View style={styles.topBarLeft}>
|
||||
<Text style={styles.greeting}>{greeting}</Text>
|
||||
</View>
|
||||
<View style={styles.topBarRight}>
|
||||
<TouchableOpacity
|
||||
style={styles.profileButton}
|
||||
onPress={() => {/* Navigate to profile */}}
|
||||
>
|
||||
<MaterialCommunityIcons name="account-circle" size={28} color={colors.highlight} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.languageButton}
|
||||
style={styles.iconButton}
|
||||
onPress={() => setLanguageSelectorVisible(true)}
|
||||
>
|
||||
<MaterialCommunityIcons
|
||||
name="translate"
|
||||
size={24}
|
||||
color={colors.highlight}
|
||||
/>
|
||||
<MaterialCommunityIcons name="translate" size={24} color={colors.highlight} />
|
||||
</TouchableOpacity>
|
||||
<View style={styles.avatarShell}>
|
||||
<Image
|
||||
source={{ uri: 'https://i.pravatar.cc/80?img=65' }}
|
||||
style={styles.avatar}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<SectionCard title={t('aiToday')} description={t('activeSpecialists')}>
|
||||
<View style={styles.avatarRow}>
|
||||
{avatars.map(avatar => (
|
||||
<View key={avatar.role} style={styles.avatarCard}>
|
||||
<View style={styles.avatarGlow}>
|
||||
<Image
|
||||
source={{ uri: `https://i.pravatar.cc/120?u=${avatar.role}` }}
|
||||
style={styles.avatarLarge}
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.avatarName}>{t(avatar.name.toLowerCase())}</Text>
|
||||
<Text style={styles.avatarRole}>{t(avatar.role.toLowerCase())}</Text>
|
||||
<TouchableOpacity style={styles.iconButton}>
|
||||
<MaterialCommunityIcons name="bell-outline" size={24} color={colors.highlight} />
|
||||
<View style={styles.notificationBadge}>
|
||||
<Text style={styles.notificationText}>6</Text>
|
||||
</View>
|
||||
))}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</SectionCard>
|
||||
</View>
|
||||
|
||||
{/* Company Selector Below Greeting */}
|
||||
<TouchableOpacity
|
||||
style={styles.companySelector}
|
||||
onPress={() => setCompanyDropdownVisible(true)}
|
||||
>
|
||||
<Image source={logo} style={styles.companyLogo} resizeMode="contain" />
|
||||
<View style={styles.companyInfo}>
|
||||
<Text style={styles.companyName}>{selectedCompany.name}</Text>
|
||||
<Text style={styles.industryLabel}>{selectedCompany.industry}</Text>
|
||||
</View>
|
||||
<MaterialCommunityIcons name="chevron-down" size={20} color={colors.highlightAlt} />
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Decorative Divider */}
|
||||
<View style={styles.decorativeDivider} />
|
||||
|
||||
{/* Quick Stats Cards */}
|
||||
<View style={styles.statsSection}>
|
||||
<ScrollView
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
style={styles.statsScroll}
|
||||
contentContainerStyle={styles.statsContainer}
|
||||
>
|
||||
{statItems.map((item) => (
|
||||
<StatCard
|
||||
key={item.label}
|
||||
icon={item.icon}
|
||||
label={item.label}
|
||||
value={item.value}
|
||||
trend={item.trend}
|
||||
style={{ width: 160 }}
|
||||
/>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
{/* AI Insights Summary */}
|
||||
<SummaryCard
|
||||
title="AI Insights"
|
||||
items={summaryItems}
|
||||
style={{ marginTop: spacing.md, marginBottom: spacing.lg }}
|
||||
/>
|
||||
|
||||
{/* Suggested Actions */}
|
||||
<View style={styles.sectionHeader}>
|
||||
<Text style={styles.sectionTitle}>{t('suggestedActions')}</Text>
|
||||
<Text style={styles.sectionCaption}>{t('tailoredFocus')}</Text>
|
||||
<Text style={styles.sectionTitle}>{t('homeScreen.suggestedActions')}</Text>
|
||||
<Text style={styles.sectionSubtitle}>{t('homeScreen.suggestionsSubtitle')}</Text>
|
||||
</View>
|
||||
<View style={styles.actionsList}>
|
||||
<ActionItem icon="file-document" label={t('invoices')} />
|
||||
<ActionItem icon="chart-bar" label={t('reports')} />
|
||||
<ActionItem icon="brain" label={t('aiDigest')} />
|
||||
|
||||
<View style={styles.actionsContainer}>
|
||||
{quickActions.map((action) => (
|
||||
<QuickActionCard
|
||||
key={action.label}
|
||||
icon={action.icon}
|
||||
label={action.label}
|
||||
description={action.description}
|
||||
badge={action.badge}
|
||||
color={action.color}
|
||||
onPress={() => {}}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* Company Dropdown Modal */}
|
||||
<Modal
|
||||
visible={companyDropdownVisible}
|
||||
transparent={true}
|
||||
animationType="fade"
|
||||
onRequestClose={() => setCompanyDropdownVisible(false)}
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={styles.modalOverlay}
|
||||
activeOpacity={1}
|
||||
onPress={() => setCompanyDropdownVisible(false)}
|
||||
>
|
||||
<View style={styles.companyDropdownModal}>
|
||||
<View style={styles.modalHeader}>
|
||||
<Text style={styles.modalTitle}>Select Company</Text>
|
||||
<TouchableOpacity onPress={() => setCompanyDropdownVisible(false)}>
|
||||
<MaterialCommunityIcons name="close" size={24} color={colors.highlightAlt} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{COMPANIES.map((company) => (
|
||||
<TouchableOpacity
|
||||
key={company.id}
|
||||
style={[
|
||||
styles.companyOption,
|
||||
selectedCompany.id === company.id && styles.companyOptionSelected,
|
||||
]}
|
||||
onPress={() => {
|
||||
setSelectedCompany(company);
|
||||
setCompanyDropdownVisible(false);
|
||||
}}
|
||||
>
|
||||
<View style={styles.companyOptionContent}>
|
||||
<Text style={styles.companyOptionName}>{company.name}</Text>
|
||||
<Text style={styles.companyOptionIndustry}>{company.industry}</Text>
|
||||
</View>
|
||||
{selectedCompany.id === company.id && (
|
||||
<MaterialCommunityIcons name="check-circle" size={24} color={colors.highlight} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Modal>
|
||||
|
||||
<LanguageSelector
|
||||
visible={languageSelectorVisible}
|
||||
onClose={() => setLanguageSelectorVisible(false)}
|
||||
@@ -91,137 +299,209 @@ export const HomeScreen: React.FC = () => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
headerRow: {
|
||||
topBar: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
title: {
|
||||
fontSize: 36,
|
||||
fontWeight: '900',
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.8,
|
||||
},
|
||||
headerRight: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
},
|
||||
languageButton: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: 16,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 12,
|
||||
elevation: 6,
|
||||
},
|
||||
avatarShell: {
|
||||
width: 52,
|
||||
height: 52,
|
||||
borderRadius: 18,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 12,
|
||||
elevation: 6,
|
||||
},
|
||||
avatar: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
borderRadius: 16,
|
||||
},
|
||||
avatarRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
avatarCard: {
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
topBarLeft: {
|
||||
flex: 1,
|
||||
},
|
||||
avatarGlow: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
borderRadius: 32,
|
||||
backgroundColor: 'rgba(26, 64, 54, 0.95)',
|
||||
topBarRight: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: spacing.sm,
|
||||
},
|
||||
greeting: {
|
||||
...typography.h2,
|
||||
fontSize: 22,
|
||||
color: colors.highlightAlt,
|
||||
fontWeight: '700',
|
||||
},
|
||||
profileButton: {
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: borderRadius.md,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
borderColor: colors.border,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 16 },
|
||||
shadowOpacity: 0.45,
|
||||
shadowRadius: 24,
|
||||
elevation: 14,
|
||||
},
|
||||
avatarLarge: {
|
||||
width: 78,
|
||||
height: 78,
|
||||
borderRadius: 26,
|
||||
iconButton: {
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: borderRadius.md,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
position: 'relative',
|
||||
},
|
||||
avatarName: {
|
||||
fontSize: 16,
|
||||
notificationBadge: {
|
||||
position: 'absolute',
|
||||
top: -4,
|
||||
right: -4,
|
||||
minWidth: 18,
|
||||
height: 18,
|
||||
borderRadius: 9,
|
||||
backgroundColor: '#EF4444',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 4,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.background,
|
||||
},
|
||||
notificationText: {
|
||||
...typography.caption,
|
||||
fontSize: 10,
|
||||
color: '#FFFFFF',
|
||||
fontWeight: '800',
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.4,
|
||||
},
|
||||
avatarRole: {
|
||||
fontSize: 13,
|
||||
companySelector: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: spacing.md,
|
||||
paddingVertical: spacing.sm,
|
||||
paddingHorizontal: spacing.md,
|
||||
borderRadius: borderRadius.lg,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
marginBottom: spacing.lg,
|
||||
...shadows.md,
|
||||
},
|
||||
companyLogo: {
|
||||
width: 44,
|
||||
height: 44,
|
||||
},
|
||||
companyInfo: {
|
||||
flex: 1,
|
||||
},
|
||||
companyName: {
|
||||
...typography.h4,
|
||||
fontSize: 16,
|
||||
color: colors.highlightAlt,
|
||||
fontWeight: '700',
|
||||
},
|
||||
industryLabel: {
|
||||
...typography.caption,
|
||||
fontSize: 11,
|
||||
color: colors.textSecondary,
|
||||
marginTop: 2,
|
||||
},
|
||||
decorativeDivider: {
|
||||
height: 1,
|
||||
backgroundColor: colors.highlight,
|
||||
marginVertical: spacing.lg,
|
||||
opacity: 0.5,
|
||||
},
|
||||
statsSection: {
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
welcomeSection: {
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
subtitle: {
|
||||
...typography.body,
|
||||
color: colors.textSecondary,
|
||||
fontWeight: '600',
|
||||
letterSpacing: 0.2,
|
||||
},
|
||||
sectionHeader: {
|
||||
gap: 6,
|
||||
marginBottom: spacing.lg,
|
||||
},
|
||||
sectionTitle: {
|
||||
fontSize: 22,
|
||||
fontWeight: '800',
|
||||
...typography.h3,
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.4,
|
||||
},
|
||||
sectionCaption: {
|
||||
fontSize: 14,
|
||||
sectionSubtitle: {
|
||||
...typography.caption,
|
||||
color: colors.textSecondary,
|
||||
fontWeight: '600',
|
||||
letterSpacing: 0.2,
|
||||
marginTop: 4,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
statsScroll: {
|
||||
marginBottom: spacing.sm,
|
||||
marginHorizontal: -spacing.xl,
|
||||
paddingHorizontal: spacing.xl,
|
||||
},
|
||||
actionItem: {
|
||||
companyDropdownButton: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 18,
|
||||
paddingHorizontal: 22,
|
||||
borderRadius: 18,
|
||||
backgroundColor: 'rgba(26, 64, 54, 0.92)',
|
||||
gap: spacing.sm,
|
||||
paddingVertical: spacing.xs,
|
||||
},
|
||||
businessName: {
|
||||
...typography.h3,
|
||||
fontSize: 18,
|
||||
color: colors.highlightAlt,
|
||||
fontWeight: '700',
|
||||
},
|
||||
logoImage: {
|
||||
width: 52,
|
||||
height: 52,
|
||||
},
|
||||
logoText: {
|
||||
...typography.h4,
|
||||
color: colors.background,
|
||||
fontWeight: '900',
|
||||
},
|
||||
statsContainer: {
|
||||
gap: spacing.md,
|
||||
paddingRight: spacing.xl,
|
||||
},
|
||||
actionsContainer: {
|
||||
gap: spacing.md,
|
||||
},
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: spacing.xl,
|
||||
},
|
||||
companyDropdownModal: {
|
||||
backgroundColor: colors.surface,
|
||||
borderRadius: borderRadius.lg,
|
||||
width: '100%',
|
||||
maxWidth: 400,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
shadowColor: colors.shadow,
|
||||
shadowOffset: { width: 0, height: 12 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 16,
|
||||
elevation: 8,
|
||||
gap: 14,
|
||||
...shadows.lg,
|
||||
},
|
||||
actionLabel: {
|
||||
modalHeader: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: spacing.lg,
|
||||
borderBottomWidth: 2,
|
||||
borderBottomColor: colors.border,
|
||||
},
|
||||
modalTitle: {
|
||||
...typography.h3,
|
||||
color: colors.highlightAlt,
|
||||
},
|
||||
companyOption: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: spacing.lg,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.border,
|
||||
},
|
||||
companyOptionSelected: {
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
},
|
||||
companyOptionContent: {
|
||||
flex: 1,
|
||||
color: colors.textPrimary,
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
companyOptionName: {
|
||||
...typography.h4,
|
||||
color: colors.highlightAlt,
|
||||
marginBottom: 4,
|
||||
},
|
||||
companyOptionIndustry: {
|
||||
...typography.caption,
|
||||
color: colors.textSecondary,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,98 +1,214 @@
|
||||
import React from 'react';
|
||||
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||
import { Image, StyleSheet, Text, View, TouchableOpacity, ScrollView } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { colors } from '../theme/colors';
|
||||
import { colors, spacing, borderRadius, typography, shadows, iconSizes } from '../theme';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import { MoreStackParamList } from '../types/navigation';
|
||||
import { PrimaryButton } from '../components/PrimaryButton';
|
||||
|
||||
type Props = NativeStackScreenProps<MoreStackParamList, 'Profile'>;
|
||||
|
||||
export const ProfileScreen: React.FC<Props> = ({ navigation }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// Profile Section Options
|
||||
const profileOptions = [
|
||||
{ icon: 'account-circle', label: t('userInfo') },
|
||||
{ icon: 'credit-card', label: t('subscription') },
|
||||
{ icon: 'connection', label: t('integrations') },
|
||||
{ icon: 'bell', label: t('notifications') },
|
||||
];
|
||||
|
||||
// Generate Section Options
|
||||
const generateOptions = [
|
||||
{ icon: 'party-popper', label: t('festivities') },
|
||||
{ icon: 'candle', label: t('diwali') },
|
||||
{ icon: 'firework', label: t('newYear') },
|
||||
{ icon: 'file-document-edit', label: t('generateScreen.templates.blogPost') },
|
||||
{ icon: 'email-newsletter', label: t('generateScreen.templates.emailCampaign') },
|
||||
{ icon: 'post', label: t('generateScreen.templates.socialMedia') },
|
||||
{ icon: 'microphone', label: t('brandVoice') },
|
||||
{ icon: 'palette', label: t('generateScreen.templates.designAssets') },
|
||||
];
|
||||
|
||||
// Other Options
|
||||
const otherOptions = [
|
||||
{ icon: 'cog', label: t('settings') },
|
||||
{ icon: 'translate', label: t('language') },
|
||||
{ icon: 'help-circle', label: t('help') },
|
||||
{ icon: 'logout', label: t('profileScreen.signOut') },
|
||||
];
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<View style={styles.headerRow}>
|
||||
<Text style={styles.title}>{t('profile')}</Text>
|
||||
<PrimaryButton
|
||||
label={t('generate')}
|
||||
variant="outline"
|
||||
style={styles.generateButton}
|
||||
onPress={() => navigation.navigate('Generate')}
|
||||
<Screen showBackground={true}>
|
||||
{/* Header with Profile Info */}
|
||||
<View style={styles.header}>
|
||||
<Image
|
||||
source={{ uri: 'https://i.pravatar.cc/140?img=68' }}
|
||||
style={styles.profileAvatar}
|
||||
/>
|
||||
<View style={styles.profileInfo}>
|
||||
<Text style={styles.profileName}>{t('johnDoe')}</Text>
|
||||
<Text style={styles.profileRole}>{t('executiveDirector')}</Text>
|
||||
<Text style={styles.profileCompany}>{t('businessInc')}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<SectionCard title={t('johnDoe')} description={t('businessInc')}>
|
||||
<View style={styles.profileRow}>
|
||||
<Image
|
||||
source={{ uri: 'https://i.pravatar.cc/140?img=68' }}
|
||||
style={styles.profileAvatar}
|
||||
/>
|
||||
<View style={styles.profileMeta}>
|
||||
<Text style={styles.profileTitle}>{t('executiveDirector')}</Text>
|
||||
<Text style={styles.profileCaption}>{t('memberSince')}</Text>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{/* Profile Section */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>{t('profileScreen.profileSettings')}</Text>
|
||||
<View style={styles.optionsGrid}>
|
||||
{profileOptions.map((option, index) => (
|
||||
<TouchableOpacity key={index} style={styles.optionCard}>
|
||||
<View style={styles.iconContainer}>
|
||||
<MaterialCommunityIcons
|
||||
name={option.icon}
|
||||
size={iconSizes.xl}
|
||||
color={colors.highlight}
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.optionLabel} numberOfLines={2}>
|
||||
{option.label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</SectionCard>
|
||||
|
||||
<View style={styles.actionsList}>
|
||||
<ListButton label={t('userInfo')} />
|
||||
<ListButton label={t('subscription')} />
|
||||
<ListButton label={t('integrations')} />
|
||||
<ListButton label={t('notifications')} />
|
||||
</View>
|
||||
{/* Generate Section */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>{t('profileScreen.generateContent')}</Text>
|
||||
<View style={styles.optionsGrid}>
|
||||
{generateOptions.map((option, index) => (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
style={styles.optionCard}
|
||||
onPress={() => navigation.navigate('Generate')}
|
||||
>
|
||||
<View style={styles.iconContainer}>
|
||||
<MaterialCommunityIcons
|
||||
name={option.icon}
|
||||
size={iconSizes.xl}
|
||||
color={colors.highlight}
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.optionLabel} numberOfLines={2}>
|
||||
{option.label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Other Options Section */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>{t('profileScreen.more')}</Text>
|
||||
<View style={styles.optionsGrid}>
|
||||
{otherOptions.map((option, index) => (
|
||||
<TouchableOpacity key={index} style={styles.optionCard}>
|
||||
<View style={styles.iconContainer}>
|
||||
<MaterialCommunityIcons
|
||||
name={option.icon}
|
||||
size={iconSizes.xl}
|
||||
color={colors.highlight}
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.optionLabel} numberOfLines={2}>
|
||||
{option.label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
headerRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
},
|
||||
title: {
|
||||
fontSize: 32,
|
||||
fontWeight: '900',
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.8,
|
||||
},
|
||||
generateButton: {
|
||||
width: 120,
|
||||
height: 42,
|
||||
},
|
||||
profileRow: {
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 18,
|
||||
gap: spacing.lg,
|
||||
marginBottom: spacing.xxl,
|
||||
paddingBottom: spacing.lg,
|
||||
borderBottomWidth: 2,
|
||||
borderBottomColor: colors.border,
|
||||
},
|
||||
profileAvatar: {
|
||||
width: 92,
|
||||
height: 92,
|
||||
borderRadius: 30,
|
||||
width: 72,
|
||||
height: 72,
|
||||
borderRadius: borderRadius.xl,
|
||||
borderWidth: 3,
|
||||
borderColor: colors.borderStrong,
|
||||
},
|
||||
profileMeta: {
|
||||
gap: 4,
|
||||
profileInfo: {
|
||||
flex: 1,
|
||||
gap: spacing.xs,
|
||||
},
|
||||
profileTitle: {
|
||||
fontSize: 17,
|
||||
fontWeight: '800',
|
||||
profileName: {
|
||||
...typography.h2,
|
||||
fontSize: 20,
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 0.4,
|
||||
},
|
||||
profileCaption: {
|
||||
profileRole: {
|
||||
...typography.bodyBold,
|
||||
fontSize: 14,
|
||||
color: colors.textSecondary,
|
||||
fontWeight: '600',
|
||||
letterSpacing: 0.2,
|
||||
color: colors.textPrimary,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
profileCompany: {
|
||||
...typography.caption,
|
||||
color: colors.textSecondary,
|
||||
},
|
||||
section: {
|
||||
marginBottom: spacing.xxl,
|
||||
},
|
||||
sectionTitle: {
|
||||
...typography.h3,
|
||||
fontSize: 18,
|
||||
color: colors.highlightAlt,
|
||||
marginBottom: spacing.lg,
|
||||
fontWeight: '700',
|
||||
},
|
||||
optionsGrid: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: spacing.md,
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
optionCard: {
|
||||
width: '31%',
|
||||
minWidth: 100,
|
||||
aspectRatio: 1,
|
||||
backgroundColor: colors.surfaceAlt,
|
||||
borderRadius: borderRadius.lg,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.border,
|
||||
padding: spacing.md,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
...shadows.md,
|
||||
},
|
||||
iconContainer: {
|
||||
width: 52,
|
||||
height: 52,
|
||||
borderRadius: borderRadius.md,
|
||||
backgroundColor: colors.surface,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: spacing.sm,
|
||||
},
|
||||
optionLabel: {
|
||||
...typography.caption,
|
||||
fontSize: 11,
|
||||
fontWeight: '700',
|
||||
color: colors.highlightAlt,
|
||||
textAlign: 'center',
|
||||
lineHeight: 14,
|
||||
paddingHorizontal: spacing.xs,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,85 +1 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import { Screen } from '../components/Screen';
|
||||
import { SectionCard } from '../components/SectionCard';
|
||||
import { ListButton } from '../components/ListButton';
|
||||
import { TaskHeader } from '../components/TaskHeader';
|
||||
import { TasksStackParamList } from '../types/navigation';
|
||||
import { colors } from '../theme/colors';
|
||||
|
||||
type Props = NativeStackScreenProps<TasksStackParamList, 'Strategy'>;
|
||||
|
||||
export const StrategyScreen: React.FC<Props> = ({ navigation }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Screen>
|
||||
<TaskHeader
|
||||
title={t('strategy')}
|
||||
caption={t('warRoom')}
|
||||
active="Strategy"
|
||||
onNavigate={screen => navigation.navigate(screen)}
|
||||
/>
|
||||
|
||||
<SectionCard title={t('swot')} description={t('boardSnapshot')}>
|
||||
<View style={styles.grid}>
|
||||
{['S', 'W', 'O', 'T'].map(letter => (
|
||||
<View key={letter} style={styles.gridCell}>
|
||||
<Text style={styles.gridLetter}>{letter}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard title={t('aiItsuline')} description={t('momentumPlay')}>
|
||||
<Text style={styles.cardBody}>
|
||||
{t('rivalExpansion')}
|
||||
</Text>
|
||||
</SectionCard>
|
||||
|
||||
<View style={styles.actionsList}>
|
||||
<ListButton label={t('initiatives')} />
|
||||
<ListButton label={t('scorecards')} />
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
grid: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: 12,
|
||||
},
|
||||
gridCell: {
|
||||
width: '47%',
|
||||
aspectRatio: 1,
|
||||
borderRadius: 20,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.borderStrong,
|
||||
backgroundColor: 'rgba(26, 64, 54, 0.92)',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 12 },
|
||||
shadowOpacity: 0.4,
|
||||
shadowRadius: 16,
|
||||
elevation: 12,
|
||||
},
|
||||
gridLetter: {
|
||||
fontSize: 38,
|
||||
fontWeight: '900',
|
||||
color: colors.highlightAlt,
|
||||
letterSpacing: 1,
|
||||
},
|
||||
cardBody: {
|
||||
fontSize: 14,
|
||||
color: colors.textSecondary,
|
||||
lineHeight: 22,
|
||||
},
|
||||
actionsList: {
|
||||
gap: 14,
|
||||
},
|
||||
});
|
||||
export { TasksScreen as StrategyScreen } from './TasksScreen';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { StyleSheet, Text, View, Image } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
import { Screen } from '../components/Screen';
|
||||
@@ -7,18 +7,17 @@ import { PrimaryButton } from '../components/PrimaryButton';
|
||||
import { colors } from '../theme/colors';
|
||||
import { RootStackParamList } from '../types/navigation';
|
||||
|
||||
const logo = require('../assets/ic_launcher_foreground.png');
|
||||
|
||||
type Props = NativeStackScreenProps<RootStackParamList, 'Welcome'>;
|
||||
|
||||
export const WelcomeScreen: React.FC<Props> = ({ navigation }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Screen scrollable={false} contentStyle={styles.content} showBackground={true}>
|
||||
<Screen scrollable={false} contentStyle={styles.content} showBackground={true} showAssistant={false}>
|
||||
<View style={styles.brandMark}>
|
||||
<View style={styles.glowRing} />
|
||||
<View style={styles.brandBadge}>
|
||||
<Text style={styles.brandInitial}>PZ</Text>
|
||||
</View>
|
||||
<Image source={logo} style={styles.logoImage} resizeMode="contain" />
|
||||
</View>
|
||||
<View style={styles.heroTextWrapper}>
|
||||
<Text style={styles.heroTitle}>
|
||||
@@ -33,12 +32,12 @@ export const WelcomeScreen: React.FC<Props> = ({ navigation }) => {
|
||||
<View style={styles.buttonStack}>
|
||||
<PrimaryButton
|
||||
label={t('signUp')}
|
||||
onPress={() => navigation.replace('MainTabs')}
|
||||
onPress={() => navigation.navigate('Signup')}
|
||||
/>
|
||||
<PrimaryButton
|
||||
label={t('logIn')}
|
||||
variant="outline"
|
||||
onPress={() => navigation.replace('MainTabs')}
|
||||
onPress={() => navigation.navigate('Login')}
|
||||
/>
|
||||
</View>
|
||||
</Screen>
|
||||
@@ -54,40 +53,14 @@ const styles = StyleSheet.create({
|
||||
gap: 48,
|
||||
},
|
||||
brandMark: {
|
||||
width: 130,
|
||||
height: 130,
|
||||
borderRadius: 42,
|
||||
borderWidth: 3,
|
||||
borderColor: colors.borderStrong,
|
||||
width: 200,
|
||||
height: 200,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'rgba(6, 35, 31, 0.95)',
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 18 },
|
||||
shadowOpacity: 0.5,
|
||||
shadowRadius: 28,
|
||||
elevation: 16,
|
||||
},
|
||||
glowRing: {
|
||||
position: 'absolute',
|
||||
width: 120,
|
||||
height: 120,
|
||||
borderRadius: 38,
|
||||
backgroundColor: colors.glowGold,
|
||||
opacity: 0.4,
|
||||
},
|
||||
brandBadge: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: 28,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: colors.highlight,
|
||||
shadowColor: colors.highlight,
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.6,
|
||||
shadowRadius: 16,
|
||||
elevation: 10,
|
||||
logoImage: {
|
||||
width: 200,
|
||||
height: 200,
|
||||
},
|
||||
brandInitial: {
|
||||
fontSize: 32,
|
||||
|
||||
Reference in New Issue
Block a user