Skip to content
Merged
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
14 changes: 3 additions & 11 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ const path = require('path');

module.exports = {
extends: ['expo', 'plugin:tailwindcss/recommended', 'prettier'],
plugins: [
'prettier',
'unicorn',
'@typescript-eslint',
'unused-imports',
'tailwindcss',
'simple-import-sort',
'eslint-plugin-react-compiler',
],
plugins: ['prettier', 'unicorn', '@typescript-eslint', 'unused-imports', 'tailwindcss', 'simple-import-sort', 'eslint-plugin-react-compiler'],
parserOptions: {
project: './tsconfig.json',
},
Expand Down Expand Up @@ -43,9 +35,9 @@ module.exports = {
'simple-import-sort/exports': 'error', // Export configuration for `eslint-plugin-simple-import-sort`
'@typescript-eslint/no-unused-vars': 'off',
'tailwindcss/no-custom-classname': 'off',
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-imports': 'off',
'unused-imports/no-unused-vars': [
'error',
'off',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
Expand Down
17 changes: 3 additions & 14 deletions .github/workflows/react-native-cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,8 @@ jobs:
- name: 📦 Install dependencies
run: pnpm install

- name: 🧪 Run TypeScript check
run: pnpm tsc

- name: 🧹 Run ESLint
run: pnpm lint

- name: 🎨 Run Prettier check
run: pnpm format:check

- name: 🧪 Run Jest Tests
run: pnpm test

- name: 🧪 Run React Native Testing Library Tests
run: pnpm test:rntl
- name: 🧪 Run Checks and Tests
run: pnpm check-all

build-and-deploy:
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')) || github.event_name == 'workflow_dispatch'
Expand All @@ -96,6 +84,7 @@ jobs:
- platform: ios
runs-on: macos-latest
runs-on: ${{ matrix.platform == 'ios' && 'macos-latest' || 'ubuntu-latest' }}
environment: RNBuild
steps:
- name: 🏗 Checkout repository
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion expo-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/// <reference types="expo/types" />

// NOTE: This file should not be edited and should be in your git ignore
// NOTE: This file should not be edited and should be in your git ignore
10 changes: 1 addition & 9 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ module.exports = {
preset: 'jest-expo',
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
testMatch: ['**/?(*.)+(spec|test).ts?(x)'],
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!**/coverage/**',
'!**/node_modules/**',
'!**/babel.config.js',
'!**/jest.setup.js',
'!**/docs/**',
'!**/cli/**',
],
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/coverage/**', '!**/node_modules/**', '!**/babel.config.js', '!**/jest.setup.js', '!**/docs/**', '!**/cli/**'],
moduleFileExtensions: ['js', 'ts', 'tsx'],
moduleDirectories: ['node_modules', '<rootDir>/'],
transformIgnorePatterns: [
Expand Down
17 changes: 3 additions & 14 deletions lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
module.exports = {
'**/*.{js,jsx,ts,tsx}': (filenames) => [
`npx eslint --fix ${filenames
.map((filename) => `"${filename}"`)
.join(' ')}`,
],
'**/*.(md|json)': (filenames) =>
`npx prettier --write ${filenames
.map((filename) => `"${filename}"`)
.join(' ')}`,
'src/translations/*.(json)': (filenames) => [
`npx eslint --fix ${filenames
.map((filename) => `"${filename}"`)
.join(' ')}`,
],
'**/*.{js,jsx,ts,tsx}': (filenames) => [`npx eslint --fix ${filenames.map((filename) => `"${filename}"`).join(' ')}`],
'**/*.(md|json)': (filenames) => `npx prettier --write ${filenames.map((filename) => `"${filename}"`).join(' ')}`,
'src/translations/*.(json)': (filenames) => [`npx eslint --fix ${filenames.map((filename) => `"${filename}"`).join(' ')}`],
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
"@expo/config": "~10.0.3",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react-native": "^12.7.2",
"@types/geojson": "^7946.0.16",
"@types/i18n-js": "^3.8.9",
"@types/jest": "^29.5.12",
"@types/lodash.memoize": "^4.1.9",
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 9 additions & 16 deletions scripts/i18next-syntax-validation.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
const validate = (message = "") => {
if (!(message || "").trim()) {
throw new SyntaxError("Message is Empty.");
const validate = (message = '') => {
if (!(message || '').trim()) {
throw new SyntaxError('Message is Empty.');
}
if (typeof message !== "string") {
throw new TypeError("Message must be a String.");
if (typeof message !== 'string') {
throw new TypeError('Message must be a String.');
}
if (
(message.includes("{") || message.includes("}")) &&
!/{{ ?(?:- |\w+?)(, ?)?\w+? ?}}/g.test(message)
) {
throw new SyntaxError(
"Interpolation error. See: https://www.i18next.com/misc/json-format",
);
if ((message.includes('{') || message.includes('}')) && !/{{ ?(?:- |\w+?)(, ?)?\w+? ?}}/g.test(message)) {
throw new SyntaxError('Interpolation error. See: https://www.i18next.com/misc/json-format');
}
if (message.includes("$t(") && !/\$t\([\w]+:\w+(?:\.\w+)*\)/g.test(message)) {
throw new SyntaxError(
"Nesting error. See: https://www.i18next.com/misc/json-format",
);
if (message.includes('$t(') && !/\$t\([\w]+:\w+(?:\.\w+)*\)/g.test(message)) {
throw new SyntaxError('Nesting error. See: https://www.i18next.com/misc/json-format');
}
};

Expand Down
55 changes: 8 additions & 47 deletions src/api/calls/callFiles.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import axios, {
type AxiosProgressEvent,
type AxiosRequestConfig,
type AxiosResponse,
} from 'axios';
import axios, { type AxiosProgressEvent, type AxiosRequestConfig, type AxiosResponse } from 'axios';

import { createApiEndpoint } from '@/api/common/client';
import { type CallFilesResult } from '@/models/v4/callFiles/callFilesResult';
Expand Down Expand Up @@ -33,10 +29,7 @@ const getCallFilesApi = createApiEndpoint('/CallFiles/GetFilesForCall');
const saveCallFileApi = createApiEndpoint('/CallFiles/SaveCallFile');

// Function to download a file with progress reporting
export const getCallAttachmentFile = async (
url: string,
options: DownloadOptions = {}
): Promise<Blob> => {
export const getCallAttachmentFile = async (url: string, options: DownloadOptions = {}): Promise<Blob> => {
const { onEvent, headers = {}, timeout = 30000 } = options;

try {
Expand All @@ -51,9 +44,7 @@ export const getCallAttachmentFile = async (
timeout,
onDownloadProgress: (progressEvent: AxiosProgressEvent) => {
if (progressEvent.total) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);

// Notify progress event
onEvent?.({
Expand All @@ -79,8 +70,7 @@ export const getCallAttachmentFile = async (
// Notify error event
onEvent?.({
type: 'error',
error:
error instanceof Error ? error : new Error('Unknown error occurred'),
error: error instanceof Error ? error : new Error('Unknown error occurred'),
});

throw error;
Expand All @@ -99,11 +89,7 @@ export const saveBlobAsFile = (blob: Blob, fileName: string): void => {
window.URL.revokeObjectURL(url);
};

export const getFiles = async (
callId: string,
includeData: boolean,
type: number
) => {
export const getFiles = async (callId: string, includeData: boolean, type: number) => {
const response = await getCallFilesApi.get<CallFilesResult>({
callId: callId,
includeData: includeData,
Expand Down Expand Up @@ -139,16 +125,7 @@ export const getCallAudio = async (callId: string, includeData: boolean) => {
return response.data;
};

export const saveCallFile = async (
callId: string,
userId: string,
note: string,
name: string,
latitude: number | null,
longitude: number | null,
file: string,
type: number
) => {
export const saveCallFile = async (callId: string, userId: string, note: string, name: string, latitude: number | null, longitude: number | null, file: string, type: number) => {
let data = {
CallId: callId,
UserId: userId,
Expand All @@ -171,26 +148,10 @@ export const saveCallFile = async (
return response.data;
};

export const saveCallImage = async (
callId: string,
userId: string,
note: string,
name: string,
latitude: number | null,
longitude: number | null,
file: string
) => {
export const saveCallImage = async (callId: string, userId: string, note: string, name: string, latitude: number | null, longitude: number | null, file: string) => {
return saveCallFile(callId, userId, note, name, latitude, longitude, file, 2);
};

export const saveCallFileAttachment = async (
callId: string,
userId: string,
note: string,
name: string,
latitude: number | null,
longitude: number | null,
file: string
) => {
export const saveCallFileAttachment = async (callId: string, userId: string, note: string, name: string, latitude: number | null, longitude: number | null, file: string) => {
return saveCallFile(callId, userId, note, name, latitude, longitude, file, 3);
};
8 changes: 1 addition & 7 deletions src/api/calls/callNotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@ export const getCallNotes = async (callId: string) => {
return response.data;
};

export const saveCallNote = async (
callId: string,
userId: string,
note: string,
latitude: number | null,
longitude: number | null
) => {
export const saveCallNote = async (callId: string, userId: string, note: string, latitude: number | null, longitude: number | null) => {
let data = {
CallId: callId,
UserId: userId,
Expand Down
6 changes: 3 additions & 3 deletions src/api/calls/callPriorities.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createApiEndpoint } from '@/api/common/client';
import { CallPrioritiesResult } from '@/models/v4/callPriorities/callPrioritiesResult';
import { type CallPrioritiesResult } from '@/models/v4/callPriorities/callPrioritiesResult';

import { createCachedApiEndpoint } from '../common/cached-client';

const callsPrioritesApi = createCachedApiEndpoint('/CallPriorities/GetAllCallPriorites', {
ttl: (60 * 1000) * 2880, // Cache for 2 days
ttl: 60 * 1000 * 2880, // Cache for 2 days
enabled: true,
});

Expand Down
7 changes: 4 additions & 3 deletions src/api/calls/callTypes.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { CallTypesResult } from '@/models/v4/callTypes/callTypesResult';
import { type CallTypesResult } from '@/models/v4/callTypes/callTypesResult';

import { createCachedApiEndpoint } from '../common/cached-client';

const callsTypesApi = createCachedApiEndpoint('/CallTypes/GetAllCallTypes', {
ttl: (60 * 1000) * 2880, // Cache for 2 days
ttl: 60 * 1000 * 2880, // Cache for 2 days
enabled: true,
});

export const getCallTypes = async () => {
const response = await callsTypesApi.get<CallTypesResult>();
return response.data;
};
};
7 changes: 4 additions & 3 deletions src/api/calls/calls.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { type ActiveCallsResult } from '@/models/v4/calls/activeCallsResult';
import { type CallExtraDataResult } from '@/models/v4/calls/callExtraDataResult';
import { type CallResult } from '@/models/v4/calls/callResult';

import { createCachedApiEndpoint } from '../common/cached-client';
import { ActiveCallsResult } from '@/models/v4/calls/activeCallsResult';
import { createApiEndpoint } from '../common/client';
import { CallExtraDataResult } from '@/models/v4/calls/callExtraDataResult';
import { CallResult } from '@/models/v4/calls/callResult';

const callsApi = createCachedApiEndpoint('/Calls/GetActiveCalls', {
ttl: 60 * 1000, // Cache for 60 seconds
Expand Down
22 changes: 8 additions & 14 deletions src/api/common/cached-client.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { AxiosResponse } from 'axios';
import { createApiEndpoint } from './client';
import { type AxiosResponse } from 'axios';

import { cacheManager } from '@/lib/cache/cache-manager';

import { createApiEndpoint } from './client';

interface CacheConfig {
ttl?: number; // Time to live in milliseconds
enabled?: boolean; // Whether to use cache for this endpoint
}

export const createCachedApiEndpoint = (
endpoint: string,
cacheConfig: CacheConfig = { enabled: true }
) => {
export const createCachedApiEndpoint = (endpoint: string, cacheConfig: CacheConfig = { enabled: true }) => {
const api = createApiEndpoint(endpoint);
const defaultTTL = 5 * 60 * 1000; // 5 minutes

return {
get: async <T,>(params?: Record<string, unknown>): Promise<AxiosResponse<T>> => {
get: async <T>(params?: Record<string, unknown>): Promise<AxiosResponse<T>> => {
if (!cacheConfig.enabled) {
return api.get<T>(params);
}
Expand All @@ -32,16 +31,11 @@ export const createCachedApiEndpoint = (
}

const response = await api.get<T>(params);
cacheManager.set(
endpoint,
response.data,
params,
cacheConfig.ttl || defaultTTL
);
cacheManager.set(endpoint, response.data, params, cacheConfig.ttl || defaultTTL);
return response;
},
post: api.post,
put: api.put,
delete: api.delete,
};
};
};
Loading
Loading