Vagabonds-Labs / cofiblocks

Welcome to Cofiblocks marketplace: A Starknet web3 platform to innovate Costa Rica coffee industry. Cofiblocks connects small coffee farmers directly with coffee lovers, cutting out unnecessary intermediaries.
https://www.cofiblocks.com/
10 stars 20 forks source link

Refactor Order Management Logic into Custom Hook #57

Open evgongora opened 2 days ago

evgongora commented 2 days ago

Extract shared order management logic into custom hook

Description:

The my-ordersand my-sales pages contain significant duplicate logic for filtering, searching, and state management. We should extract this into reusable hooks.

Code References:

my-orders

export default function MyOrders() {
    const [searchTerm, setSearchTerm] = useState("");
    const [isFiltersModalOpen, setIsFiltersModalOpen] = useState(false);
    const [filteredOrders, setFilteredOrders] = useState(mockedOrders);
    const [activeFilters, setActiveFilters] = useState<FormValues>({});
    const router = useRouter();

    const openFiltersModal = () => {
        setIsFiltersModalOpen(true);
    };

    const closeFiltersModal = () => {
        setIsFiltersModalOpen(false);
    };

    const { control, handleSubmit } = useForm<FormValues>({
        resolver: zodResolver(filtersSchema),
        defaultValues: {
            statusPaid: false,
            statusPrepared: false,
            statusShipped: false,
            statusDelivered: false,
        },
    });

    const onSubmit = (data: FormValues) => {
        console.log(data);
        setActiveFilters(data);
        closeFiltersModal();
    };

    const handleItemClick = (id: string) => {
        router.push(`/user/my-orders/${id}`);
    };

    useEffect(() => {
        const newFilteredOrders = mockedOrders
            .map((orderGroup) => ({
                ...orderGroup,
                items: orderGroup.items.filter((item) => {
                    const matchesSearch = searchTerm
                        ? item.sellerName.toLowerCase().includes(searchTerm.toLowerCase())
                        : true;

                    const activeStatusFilters = [
                        activeFilters.statusPaid,
                        activeFilters.statusPrepared,
                        activeFilters.statusShipped,
                        activeFilters.statusDelivered,
                    ];

                    const matchesStatus = activeStatusFilters.some(Boolean)
                        ? (activeFilters.statusPaid &&
                                item.status === SalesStatusEnum.Paid) ??
                            (activeFilters.statusPrepared &&
                                item.status === SalesStatusEnum.Prepared) ??
                            (activeFilters.statusShipped &&
                                item.status === SalesStatusEnum.Shipped) ??
                            (activeFilters.statusDelivered &&
                                item.status === SalesStatusEnum.Delivered)
                        : true;

                    return matchesSearch && matchesStatus;
                }),
            }))
            .filter((orderGroup) => orderGroup.items.length > 0);

        if (!searchTerm && !Object.values(activeFilters).some(Boolean)) {
            setFilteredOrders(mockedOrders);
        } else {
            setFilteredOrders(newFilteredOrders);
        }
    }, [searchTerm, activeFilters]);

my-sales

export default function MySales() {
    const [searchTerm, setSearchTerm] = useState("");
    const [isFiltersModalOpen, setIsFiltersModalOpen] = useState(false);
    const [filteredOrders, setFilteredOrders] = useState(mockedOrders);
    const [activeFilters, setActiveFilters] = useState<FormValues>({});
    const router = useRouter();

    const openFiltersModal = () => {
        setIsFiltersModalOpen(true);
    };

    const closeFiltersModal = () => {
        setIsFiltersModalOpen(false);
    };

    const { control, handleSubmit } = useForm<FormValues>({
        resolver: zodResolver(filtersSchema),
        defaultValues: {
            statusPaid: false,
            statusPrepared: false,
            statusShipped: false,
            statusDelivered: false,
            deliveryAddress: false,
            deliveryMeetup: false,
        },
    });

    const onSubmit = (data: FormValues) => {
        console.log(data);
        setActiveFilters(data);
        closeFiltersModal();
    };

    const handleItemClick = (id: string) => {
        router.push(`/user/my-sales/${id}`);
    };

    useEffect(() => {
        const newFilteredOrders = mockedOrders
            .map((orderGroup) => ({
                ...orderGroup,
                items: orderGroup.items.filter((item) => {
                    const matchesSearch = searchTerm
                        ? item.buyerName.toLowerCase().includes(searchTerm.toLowerCase())
                        : true;

                    const activeStatusFilters = [
                        activeFilters.statusPaid,
                        activeFilters.statusPrepared,
                        activeFilters.statusShipped,
                        activeFilters.statusDelivered,
                    ];

                    const matchesStatus = !activeStatusFilters.some(Boolean)
                        ? true
                        : (activeFilters.statusPaid &&
                                item.status === SalesStatusEnum.Paid) ??
                            (activeFilters.statusPrepared &&
                                item.status === SalesStatusEnum.Prepared) ??
                            (activeFilters.statusShipped &&
                                item.status === SalesStatusEnum.Shipped) ??
                            (activeFilters.statusDelivered &&
                                item.status === SalesStatusEnum.Delivered);

                    const activeDeliveryFilters = [
                        activeFilters.deliveryAddress,
                        activeFilters.deliveryMeetup,
                    ];

                    const matchesDelivery = !activeDeliveryFilters.some(Boolean)
                        ? true
                        : (activeFilters.deliveryAddress &&
                                item.delivery === DeliveryMethodEnum.Address) ??
                            (activeFilters.deliveryMeetup &&
                                item.delivery === DeliveryMethodEnum.Meetup);

                    return matchesSearch && matchesStatus && matchesDelivery;
                }),
            }))
            .filter((orderGroup) => orderGroup.items.length > 0);

        if (!searchTerm && !Object.values(activeFilters).some(Boolean)) {
            setFilteredOrders(mockedOrders);
        } else {
            setFilteredOrders(newFilteredOrders);
        }
    }, [searchTerm, activeFilters]);

Acceptance Criteria:

petersdt commented 2 days ago

@evgongora can i be assigned to work on this issue?

Luluameh commented 2 days ago

@evgongora can you assign me this issue I can handle it

martinvibes commented 2 days ago

Hey @evgongora I would love to take on this issue Kindly assign

ShantelPeters commented 1 day ago

Hello @evgongora can i please work on this issue

Benjtalkshow commented 1 day ago

@brolag and @evgongora I am a Full Stack Developer with a strong background in blockchain and extensive experience in Next.js/React, TypeScript, and Rust. I’ve made over 45 contributions to over 15 projects in the OnlyDust ecosystem, solving complex issues and delivering efficient, scalable solutions.

I will refactor the shared logic for filtering, searching, and state management from the my-orders and my-sales pages into a reusable custom hook. The hook will support dynamic filters (status, delivery method) and search functionality while ensuring clear handling of empty states. I’ll update both pages to use the new hook, reducing code duplication and improving maintainability. This approach ensures a clean, modular, and efficient implementation for managing order-related logic.

My ETA is 48hrs. Thanks

derianrddev commented 1 day ago

My Background and How It Can Be Leveraged Hello, my name is Derian Rodríguez. I am a passionate software engineer with over one year of experience. I am part of the Dojo Coding Community and have been actively contributing to open-source projects through OnlyDust. I have experience in frontend development using JavaScript/TypeScript, React, and Next.js. I would love to contribute and support the development of this project.

How I Plan on Tackling This Issue I will create a custom hook with the filtering, searching, and shared state logic between the My Orders and My Sales pages. I will use the new hook in MyOrders and MySales, removing redundant logic and simplifying the code. I will verify that the filters, search functionality, and empty states work correctly on both pages without errors.

MrRoudyk commented 1 day ago

May I try my hand at this?

Michaelkingsdev commented 1 day ago

May I handle this issue? I am an experienced frontend developer with 3 years of experience.