Skip to content

Commit

Permalink
feat: fix architecture and performance issues for my-escrows
Browse files Browse the repository at this point in the history
  • Loading branch information
brolag committed Feb 23, 2025
1 parent 965d297 commit 53d14b5
Show file tree
Hide file tree
Showing 8 changed files with 435 additions and 98 deletions.
52 changes: 52 additions & 0 deletions instructions/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Changelog

## [Unreleased]

### Refactor: Improved Escrow Service Architecture and Type Safety

#### PR Description
This PR introduces significant architectural improvements to the escrow service layer, enhancing type safety, maintainability, and performance. The changes follow industry best practices and establish a more robust foundation for the escrow functionality.

#### Key Improvements

##### Architecture & Organization
- Separated concerns between types, services, and state management
- Moved shared types to centralized `@types` directory
- Established clear boundaries between data layer and business logic
- Improved code organization following domain-driven design principles

##### Type Safety
- Consolidated duplicate type definitions
- Enhanced type definitions using TypeScript utility types (Omit, Pick)
- Improved type consistency for numeric values stored as strings
- Added proper type imports with explicit 'type' imports

##### Performance Optimizations
- Implemented proper function memoization using useCallback
- Fixed React hooks dependency arrays
- Added request deduplication in data fetching
- Improved state updates efficiency

##### Code Quality
- Removed duplicate code and redundant interfaces
- Enhanced code readability with proper formatting
- Added proper error handling for async operations
- Improved type conversions for balance handling

#### Technical Details
- Refactored `EscrowPayload` to use TypeScript's utility types
- Consolidated balance handling logic with proper type conversions
- Improved hook dependencies in `escrow-detail-dialog.hook.ts`
- Enhanced service layer with proper type definitions

#### Impact
- Reduced potential for runtime errors through enhanced type safety
- Improved maintainability through better code organization
- Enhanced performance through proper memoization and state management
- Better developer experience with clearer type definitions

#### Breaking Changes
None. All changes are backward compatible.

#### Migration
No migration needed. Changes are transparent to existing implementations.
191 changes: 191 additions & 0 deletions instructions/folder_structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# Folder Structure

.
├── README.md
├── components.json
├── docs
│   ├── CONTRIBUTORS_GUIDELINE.md
│   ├── Error_Report.xlsx
│   └── GIT_GUIDELINE.md
├── firebase.ts
├── instructions
│   ├── folder_structure.md
│   └── instructions.md
├── next-env.d.ts
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── public
│   ├── assets
│   │   ├── social-networks
│   │   │   ├── linkedin.svg
│   │   │   ├── telegram.svg
│   │   │   └── x.svg
│   │   └── stellar-expert-blue.svg
│   └── logo.png
├── src
│   ├── @types
│   │   ├── dates.entity.ts
│   │   ├── escrow.entity.ts
│   │   ├── issue.entity.ts
│   │   └── user.entity.ts
│   ├── app
│   │   ├── dashboard
│   │   │   ├── contact
│   │   │   │   └── page.tsx
│   │   │   ├── escrow
│   │   │   │   ├── initialize-escrow
│   │   │   │   └── my-escrows
│   │   │   ├── help
│   │   │   │   └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   └── report-issue
│   │   │   └── page.tsx
│   │   ├── favicon.ico
│   │   ├── fonts
│   │   │   ├── Exo2.ttf
│   │   │   ├── GeistMonoVF.woff
│   │   │   ├── GeistVF.woff
│   │   │   └── SpaceGrotesk.ttf
│   │   ├── globals.css
│   │   ├── layout.tsx
│   │   ├── page.tsx
│   │   ├── report-issue
│   │   │   └── page.tsx
│   │   └── settings
│   │   └── page.tsx
│   ├── components
│   │   ├── layout
│   │   │   ├── Bounded.tsx
│   │   │   ├── Wrappers.tsx
│   │   │   ├── footer
│   │   │   │   └── Footer.tsx
│   │   │   ├── header
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── HeaderWithoutAuth.tsx
│   │   │   │   ├── ThemeToggle.tsx
│   │   │   │   └── hooks
│   │   │   └── sidebar
│   │   │   ├── app-sidebar.tsx
│   │   │   ├── constants
│   │   │   ├── nav-main.tsx
│   │   │   ├── nav-projects.tsx
│   │   │   ├── nav-user.tsx
│   │   │   └── team-switcher.tsx
│   │   ├── modules
│   │   │   ├── auth
│   │   │   │   ├── server
│   │   │   │   └── wallet
│   │   │   ├── contact
│   │   │   │   ├── ContactForm.tsx
│   │   │   │   ├── hooks
│   │   │   │   └── schema
│   │   │   ├── dashboard
│   │   │   │   ├── hooks
│   │   │   │   └── ui
│   │   │   ├── escrow
│   │   │   │   ├── code
│   │   │   │   ├── constants
│   │   │   │   ├── hooks
│   │   │   │   ├── schema
│   │   │   │   ├── server
│   │   │   │   ├── services
│   │   │   │   ├── store
│   │   │   │   └── ui
│   │   │   ├── help
│   │   │   │   ├── constants
│   │   │   │   └── ui
│   │   │   ├── report-issue
│   │   │   │   ├── hooks
│   │   │   │   ├── schema
│   │   │   │   ├── server
│   │   │   │   └── ui
│   │   │   └── setting
│   │   │   ├── APIKeysSection.tsx
│   │   │   ├── Settings.tsx
│   │   │   ├── Sidebar.tsx
│   │   │   ├── appearanceSection.tsx
│   │   │   ├── hooks
│   │   │   ├── preferencesSection.tsx
│   │   │   ├── profileSection.tsx
│   │   │   ├── server
│   │   │   ├── services
│   │   │   ├── store
│   │   │   └── ui
│   │   ├── ui
│   │   │   ├── accordion.tsx
│   │   │   ├── avatar.tsx
│   │   │   ├── badge.tsx
│   │   │   ├── breadcrumb.tsx
│   │   │   ├── button.tsx
│   │   │   ├── calender.tsx
│   │   │   ├── card.tsx
│   │   │   ├── chart.tsx
│   │   │   ├── collapsible.tsx
│   │   │   ├── command.tsx
│   │   │   ├── dialog.tsx
│   │   │   ├── dropdown-menu.tsx
│   │   │   ├── form.tsx
│   │   │   ├── hover-card.tsx
│   │   │   ├── input.tsx
│   │   │   ├── label.tsx
│   │   │   ├── navigation-menu.tsx
│   │   │   ├── popover.tsx
│   │   │   ├── progress.tsx
│   │   │   ├── select.tsx
│   │   │   ├── separator.tsx
│   │   │   ├── sheet.tsx
│   │   │   ├── sidebar.tsx
│   │   │   ├── skeleton.tsx
│   │   │   ├── steps.tsx
│   │   │   ├── switch.tsx
│   │   │   ├── tab.tsx
│   │   │   ├── table.tsx
│   │   │   ├── textarea.tsx
│   │   │   ├── toast.tsx
│   │   │   ├── toaster.tsx
│   │   │   └── tooltip.tsx
│   │   └── utils
│   │   ├── code
│   │   │   ├── CodeBlock.tsx
│   │   │   └── FlipCard.tsx
│   │   └── ui
│   │   ├── Create.tsx
│   │   ├── Divider.tsx
│   │   ├── Loader.tsx
│   │   ├── NoData.tsx
│   │   ├── SelectSearch.tsx
│   │   └── Tooltip.tsx
│   ├── core
│   │   ├── config
│   │   │   ├── axios
│   │   │   │   └── http.ts
│   │   │   └── firebase
│   │   │   └── firebase.ts
│   │   └── store
│   │   ├── data
│   │   │   ├── @types
│   │   │   ├── index.ts
│   │   │   └── slices
│   │   └── ui
│   │   ├── @types
│   │   ├── index.ts
│   │   └── slices
│   ├── hooks
│   │   ├── layout-dashboard.hook.ts
│   │   ├── mobile.hook.ts
│   │   └── toast.hook.ts
│   ├── lib
│   │   └── utils.ts
│   └── utils
│   └── hook
│   ├── copy.hook.ts
│   ├── format.hook.ts
│   ├── input-visibility.hook.ts
│   └── valid-data.hook.ts
├── tailwind.config.ts
└── tsconfig.json


22 changes: 22 additions & 0 deletions instructions/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Overview
We're auditing this project to make sure it uses the best coding practices.

# Tasks
Act as a senior front end developer with more than 10 years of experience and a deep understanding of TypeScript, React, Next.js, Tailwind CSS, and Firebase.
Act also as a senior ux ui designer with more than 10 years of experience.


# IMPORTANT GUIDELINES DON'T IGNORE THEM
- Please be very specific in your feedback. Don't say things like "improve the code" or "make it more efficient".
- Please keep the same functionality and design.
- Provide suggestions before you code things.
- ALWAYS update the changelog.md file.
- ALWAYS think in two possible solutions and provide the best one.
- ALWAYS show your reasoning steps.

# Core Functionalities
- Best use of React
- Best use of Next.js
- Best use of Tailwind CSS
- Best use of Firebase
- Optimization and best practices for Firebase to avoid high costs
7 changes: 6 additions & 1 deletion src/@types/escrow.entity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CreatedAt, UpdatedAt } from "./dates.entity";
import type { CreatedAt, UpdatedAt } from "./dates.entity";

export type MilestoneStatus = "completed" | "approved" | "pending";

Expand Down Expand Up @@ -87,3 +87,8 @@ export type EditMilestonesPayload = {
escrow: EscrowPayload;
signer: string;
};

export interface BalanceItem {
address: string;
balance: number;
}
43 changes: 36 additions & 7 deletions src/components/modules/escrow/hooks/my-escrows.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
useGlobalAuthenticationStore,
useGlobalBoundedStore,
} from "@/core/store/data";
import { useState, useEffect, useMemo } from "react";
import { useState, useEffect, useMemo, useRef, useCallback } from "react";

interface useMyEscrowsProps {
type: string;
Expand All @@ -19,6 +19,9 @@ const useMyEscrows = ({ type }: useMyEscrowsProps) => {
const [expandedRows, setExpandedRows] = useState<string[]>([]);
const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(15);
const [isLoading, setIsLoading] = useState(false);
const fetchingRef = useRef(false);
const lastFetchKey = useRef("");

const totalPages = Math.ceil(totalEscrows / itemsPerPage);

Expand All @@ -31,15 +34,40 @@ const useMyEscrows = ({ type }: useMyEscrowsProps) => {
);
}, [escrows, currentPage, itemsPerPage]);

const memoizedFetchEscrows = useCallback(async () => {
if (!address || fetchingRef.current) return;
const fetchKey = `${address}-${type}`;
if (fetchKey === lastFetchKey.current) return;
try {
fetchingRef.current = true;
lastFetchKey.current = fetchKey;
setIsLoading(true);
await fetchAllEscrows({ address, type });
} catch (error) {
console.error("[MyEscrows] Error fetching escrows:", error);
} finally {
setIsLoading(false);
fetchingRef.current = false;
}
}, [address, type, fetchAllEscrows]);

useEffect(() => {
const fetchEscrows = async () => {
if (address) {
fetchAllEscrows({ address, type });
}
let timeoutId: NodeJS.Timeout;

const debouncedFetch = () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
memoizedFetchEscrows();
}, 100);
};

fetchEscrows();
}, []);
debouncedFetch();

return () => {
clearTimeout(timeoutId);
fetchingRef.current = false;
};
}, [memoizedFetchEscrows]);

const toggleRowExpansion = (rowId: string) => {
setExpandedRows((prev) =>
Expand All @@ -66,6 +94,7 @@ const useMyEscrows = ({ type }: useMyEscrowsProps) => {
itemsPerPageOptions,
toggleRowExpansion,
expandedRows,
isLoading,
};
};

Expand Down
Loading

0 comments on commit 53d14b5

Please sign in to comment.