📦 EqualifyEverything / equalify-dashboard

📄 bulk-property.tsx · 126 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from '~/components/alerts';
import { Button } from '~/components/buttons';
import { SEO } from '~/components/layout';
import { addProperty } from '~/services';
import { useStore } from '~/store';

const BulkProperty = () => {
    const navigate = useNavigate();
    const [isFormValid, setIsFormValid] = useState(false);
    const [data, setData] = useState([]);
    const { loading, setLoading } = useStore();
    const [current, setCurrent] = useState(1);

    const onChange = (e) => {
        const file = e.target.files[0];
        const reader = new FileReader();
        reader.onload = (e) => {
            const text = e.target.result;
            const rows = text.split('\n');
            const parsedData = rows.map(row => row.split(','));
            setData(parsedData);
        };
        reader.readAsText(file);
        return;
    }

    useEffect(() => {
        if (data?.length > 0) {
            setIsFormValid(true);
        }
        else {
            setIsFormValid(false);
        }
    }, [data]);

    const handleSubmit = async (e) => {
        e.preventDefault();
        if (!isFormValid) return;
        setLoading(true);

        try {
            const successes = [];
            const errors = [];
            for (const [index, row] of data.entries()) {
                setCurrent(index);
                try {
                    const response = await addProperty(row[0], row[1], row[2]);
                    console.log(response);
                    successes.push(row);
                }
                catch (err) {
                    errors.push(row);
                }
            }
            setLoading(false);
            toast.success({ title: 'Success', description: 'Properties added successfully!' });
            navigate('/properties');
        } catch (error) {
            setLoading(false);
            toast.error({ title: 'Error', description: 'An error occurred while adding the properties.' });
        }
    };

    return (
        <>
            <SEO
                title="Bulk Add Property - Equalify"
                description="Bulk add new propeties to Equalify to start monitoring and improving its accessibility."
                url="https://dashboard.equalify.app/properties/bulk"
            />
            <h1 id="bulk-property-heading" className="text-2xl font-bold md:text-3xl">
                Bulk Upload CSV
            </h1>

            <section
                aria-labelledby="bulk-property-heading"
                className="mt-7 space-y-6 rounded-lg bg-white p-6 shadow"
                aria-live="polite"
            >
                <form onSubmit={handleSubmit} id="bulk-property-form" className='flex flex-col gap-4'>
                    <a target='_blank' className='underline' href='/template.csv'>Example Template CSV</a>
                    <input onChange={onChange} type='file' />
                    {data.length > 0 && <div className='flex flex-col'>
                        <div>Showing first 10 rows</div>
                        {data.slice(0, 10).map((row, index) => <div key={index} className={`p-1 flex flex-row gap-2 ${index === 0 && 'bg-card'}`}>
                            {row.map((cell, index) => <div key={index} style={{ width: `${100 / data[0].length}%` }} className='truncate'>{cell}</div>)}
                        </div>)}
                        <div>...</div>
                    </div>}
                    <div className="space-x-6">
                        <Button
                            type='reset'
                            variant={'outline'}
                            className="w-fit"
                            onClick={() => navigate(-1)}
                            aria-label='Cancel adding property'
                        >
                            Cancel
                        </Button>
                        <Button
                            type="submit"
                            form="bulk-property-form"
                            className="w-fit bg-[#1D781D] text-white"
                            disabled={!isFormValid}
                            aria-disabled={!isFormValid}
                            aria-live="polite"
                        >
                            Submit
                        </Button>
                    </div>
                </form>
            </section>
            {loading && <div
                className="fixed top-0 left-0 w-full h-full bg-[#6666] flex flex-row gap-2 items-center justify-center"
            >
                <div className='animate-spin flex flex-row items-center justify-center text-center'>↻</div>
                Adding {current} of {data.length - 1} properties...
            </div>}
        </>
    );
};

export default BulkProperty;