Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
61ed8cc
doctype.data is now being accessed
Nischa1Mv Dec 9, 2025
833df0f
Merge branch 'main' of https://github.com/Nischa1Mv/offline-data-entr…
Nischa1Mv Dec 15, 2025
19c57c0
added the new doctype and adjusted the css beacuse of the long name
Nischa1Mv Jan 5, 2026
31faea1
- enhanced field visibility logic based on dynamic conditions in isFi…
Nischa1Mv Jan 5, 2026
4607b06
added CurrencyInput component and integrate it into FormDetail for cu…
Nischa1Mv Jan 5, 2026
4235eb0
added PhoneInput component and integrated it into FormDetail for phon…
Nischa1Mv Jan 5, 2026
67ea01a
added CheckboxInput component and integrated it into FormDetail for c…
Nischa1Mv Jan 6, 2026
feab457
added HeadingText component and integrated it into FormDetail for imp…
Nischa1Mv Jan 6, 2026
b575a71
added SectionBreak component and integrated it into FormDetail ,
Nischa1Mv Jan 6, 2026
029e693
only field.label will be passsed into label
Nischa1Mv Jan 6, 2026
267129e
refactor SectionBreak component to simplify label rendering logic
Nischa1Mv Jan 6, 2026
a13135b
the label for checkboxes is not needed , as it included in the compon…
Nischa1Mv Jan 6, 2026
82af9bd
refactor CheckboxInput and SectionBreak components for improved styli…
Nischa1Mv Jan 6, 2026
d78eae7
added a calender icon for data picker
Nischa1Mv Jan 6, 2026
a656e51
enhance input handling for numeric fields to restrict input types and…
Nischa1Mv Jan 6, 2026
64dc2d9
add validation functions for integer and float inputs, and format flo…
Nischa1Mv Jan 6, 2026
637f08f
add required field handling to form validation and display
Nischa1Mv Jan 6, 2026
4b971fc
refactor Forms component layout for improved styling and spacing
Nischa1Mv Jan 6, 2026
43e1bd0
refactor hash function for improved readability and structure
Nischa1Mv Jan 7, 2026
9bc82bc
refactor dropdown
Nischa1Mv Jan 8, 2026
56c97fb
refactor dropdown components for improved styling and spacing
Nischa1Mv Jan 8, 2026
0355f8b
phone number is now sedning corectly with the country code
Nischa1Mv Feb 24, 2026
c90012a
added flag to phone ninpur ui
Nischa1Mv Feb 24, 2026
5c8d89d
phone number input updated
Nischa1Mv Feb 24, 2026
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
45 changes: 45 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,13 @@ export async function getAllDoctypesFromLocal(): Promise<
}
const parsed = parseJson<StoredDoctype>(value);
if (parsed?.payload) {
// Validate that payload has the expected structure
if (!parsed.payload.data) {
return;
}
if (!parsed.payload.fields) {
return;
}
result[normalizeDoctypeName(parsed.name)] = parsed.payload;
}
});
Expand Down Expand Up @@ -352,13 +359,50 @@ const defaultFetcher = async (name: string): Promise<DocType> => {
const response = await getDoctypeByName({
path: { form_name: name },
});

const data =
(response as any)?.data?.data ??
(response as any)?.data ??
(response as any);
if (!data) {
throw new Error(`Doctype response missing data for ${name}`);
}

// Validate that we have fields array
if (!data.fields || !Array.isArray(data.fields)) {
throw new Error(`Invalid doctype structure for ${name}: missing fields array`);
}

// Check if data object exists, if not try to create it from top-level properties
if (!data.data || typeof data.data !== 'object') {
// Look for doctype metadata at the top level
const doctypeMetadata: any = {};
const metadataFields = [
'name', 'creation', 'modified', 'modified_by', 'owner', 'docStatus',
'idx', 'issingle', 'istable', 'editable_grid', 'track_changes', 'module',
'autoname', 'name_case', 'sort_field', 'sort_order', 'readonly', 'in_create',
'allow_copy', 'allow_rename', 'allow_import', 'hide_toolbar', 'track_seen',
'max_attachments', 'document_type', 'engine', 'is_submittable',
'show_name_in_global_search', 'custom', 'beta', 'has_web_view',
'allow_guest_to_view', 'qick_entry', 'is_tree', 'track_views',
'all_events_in_timeline', 'allow_auto_repeat', 'show_preview_popup',
'email_append_to', 'index_web_pages_for_search', 'docType'
];

metadataFields.forEach(field => {
if (data[field] !== undefined) {
doctypeMetadata[field] = data[field];
}
});

// If we found metadata, create the nested structure
if (Object.keys(doctypeMetadata).length > 0) {
data.data = doctypeMetadata;
} else {
throw new Error(`Invalid doctype structure for ${name}: missing data object`);
}
}

return data as DocType;
};

Expand Down Expand Up @@ -594,6 +638,7 @@ export function extractFields(docType: DocType): RawField[] {
print_hide: field.print_hide,
report_hide: field.report_hide,
depends_on: field.depends_on,
reqd: field.reqd,
}));
}

Expand Down
18 changes: 10 additions & 8 deletions src/app/components/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import DateTimePicker, {
DateTimePickerAndroid,
type DateTimePickerEvent,
} from '@react-native-community/datetimepicker';
import { Calendar } from 'lucide-react-native';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
View,
Text,
TouchableOpacity,
Modal,
Platform,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import DateTimePicker, {
DateTimePickerAndroid,
type DateTimePickerEvent,
} from '@react-native-community/datetimepicker';
import { useTheme } from '../../context/ThemeContext';
import { useTranslation } from 'react-i18next';

interface DatePickerProps {
value?: string;
Expand Down Expand Up @@ -129,6 +130,7 @@ const DatePicker: React.FC<DatePickerProps> = ({
>
{value ? formatDisplayDate(value) : placeholder}
</Text>
<Calendar color={theme.subtext} size={20} />
</TouchableOpacity>

{Platform.OS === 'ios' && datePickerVisible && (
Expand Down
69 changes: 32 additions & 37 deletions src/app/components/LinkDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { ChevronDown } from 'lucide-react-native';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
View,
Text,
TouchableOpacity,
ScrollView,
ActivityIndicator,
ScrollView,
Text,
TextInput,
TouchableOpacity,
View,
} from 'react-native';
import { ChevronDown } from 'lucide-react-native';
import { useTheme } from '../../context/ThemeContext';
import { getLinkOptionsFromLocal, saveLinkOptionsToLocal } from '../../api';
import { useNetwork } from '../../context/NetworkProvider';
import { useTheme } from '../../context/ThemeContext';
import { getLinkOptions } from '../../lib/hey-api/client/sdk.gen';
import { getLinkOptionsFromLocal, saveLinkOptionsToLocal } from '../../api';

type LinkDropdownProps = {
doctype: string; // linked doctype to fetch options for
Expand Down Expand Up @@ -41,27 +41,9 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
const hasLoadedRef = useRef(false);

const containerStyle = {
position: 'relative' as const,
zIndex: containerZIndex,
};

const dropdownStyle = {
position: 'absolute' as const,
top: 45,
left: 0,
right: 0,
zIndex: 2000,
backgroundColor: theme.dropdownBg,
borderWidth: 1.5,
borderColor: theme.border,
borderRadius: 8,
shadowColor: theme.shadow,
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.25,
shadowRadius: 8,
elevation: 20,
};

const filteredOptions = useMemo(() => {
if (!searchTerm.trim()) {
return allOptions;
Expand All @@ -75,13 +57,8 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
[filteredOptions]
);

const dropdownMaxHeight = Math.min(
Math.max(displayOptions.length, 4) * 48 + 56,
480
);

const scrollViewStyle = {
maxHeight: dropdownMaxHeight - 56,
maxHeight: 250,
};

const normalizedDoctype = useMemo(() => (doctype || '').trim(), [doctype]);
Expand Down Expand Up @@ -257,7 +234,7 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
return (
<View style={containerStyle}>
<TouchableOpacity
className="h-[40px] w-full flex-row items-center justify-between rounded-md border px-3"
className="h-[44px] w-full flex-row items-center justify-between rounded-lg border-[1.5px] px-4"
style={{
borderColor: theme.border,
backgroundColor: theme.background,
Expand All @@ -273,7 +250,7 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
{value || placeholder}
</Text>
<ChevronDown
size={16}
size={18}
color={theme.subtext}
style={{
transform: [{ rotate: isOpen ? '180deg' : '0deg' }],
Expand All @@ -282,7 +259,22 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
</TouchableOpacity>

{isOpen && (
<View style={{ ...dropdownStyle, maxHeight: dropdownMaxHeight }}>
<View
style={{
marginTop: 8,
backgroundColor: theme.dropdownBg,
borderWidth: 1.5,
borderColor: theme.border,
borderRadius: 12,
shadowColor: '#000',
shadowOffset: { width: 0, height: 6 },
shadowOpacity: 0.15,
shadowRadius: 12,
elevation: 8,
maxHeight: 250,
overflow: 'hidden',
}}
>
{loading ? (
<View className="items-center justify-center px-4 py-6">
<ActivityIndicator color={theme.subtext} />
Expand All @@ -298,13 +290,14 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
</View>
) : (
<>
<View className="px-3 pt-3">
<View className="px-3 pt-3 pb-2">
<TextInput
className="h-[40px] w-full rounded-md border px-3"
className="h-[42px] w-full rounded-lg border px-4"
style={{
borderColor: theme.border,
backgroundColor: theme.background,
color: theme.text,
fontSize: 15,
}}
value={searchTerm}
onChangeText={text => setSearchTerm(text)}
Expand All @@ -323,7 +316,7 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
return (
<TouchableOpacity
key={`${trimmedOption}-${optIndex}`}
className={`px-4 py-3 ${optIndex < displayOptions.length - 1 ? 'border-b' : ''}`}
className={`px-4 py-3.5 ${optIndex < displayOptions.length - 1 ? 'border-b' : ''}`}
style={{
backgroundColor: isSelected
? theme.dropdownSelectedBg
Expand All @@ -332,6 +325,7 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
optIndex < displayOptions.length - 1
? theme.border
: undefined,
borderBottomWidth: optIndex < displayOptions.length - 1 ? 0.5 : 0,
}}
onPress={() => {
onValueChange(trimmedOption);
Expand All @@ -341,6 +335,7 @@ const LinkDropdown: React.FC<LinkDropdownProps> = ({
style={{
color: theme.text,
fontWeight,
fontSize: 15,
}}
>
{trimmedOption}
Expand Down
Loading