Ignore:
Timestamp:
12/29/25 04:34:44 (6 months ago)
Author:
Mihail <mihail2.naumov@…>
Branches:
main
Children:
41a2f81
Parents:
f46bf5c
Message:

Added add component button, fixed several things

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pages/forge/+Page.tsx

    rf46bf5c r958bc89  
    33    Container, Paper, Typography, Box, Table, TableBody, TableCell, TableContainer, TableHead, TableRow,
    44    Button, IconButton, Avatar, TextField, Grid, Chip, CircularProgress,
    5     Menu, MenuItem, ListItemIcon
     5    Menu, MenuItem, ListItemIcon, Dialog, DialogTitle, DialogContent, DialogActions
    66} from '@mui/material';
    77import AddIcon from '@mui/icons-material/Add';
     
    1818    onRemoveComponentFromBuild,
    1919    onDeleteBuild,
    20     onGetBuildState, onGetBuildComponents
     20    onGetBuildState,
     21    onGetBuildComponents
    2122} from './forge.telefunc';
    2223
     
    5758    const [detailsOpen, setDetailsOpen] = useState<any>(null);
    5859    const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
     60    const [submitDialogOpen, setSubmitDialogOpen] = useState(false);  // NEW
     61    const [tempDescription, setTempDescription] = useState("");      // NEW
    5962    const isSubmittedRef = React.useRef(false);
    6063
     
    6366        setTotalPrice(price);
    6467    }, [slots]);
     68
     69    useEffect(() => {
     70        if (buildId && buildName.trim()) {
     71            const timeoutId = setTimeout(() => {
     72                saveBuildState({ buildId, name: buildName.trim(), description });
     73            }, 1000);
     74
     75            return () => clearTimeout(timeoutId);
     76        }
     77    }, [buildId, buildName, description]);
    6578
    6679    useEffect(() => {
     
    91104        if (urlBuildId && Number.isInteger(Number(urlBuildId)) && Number(urlBuildId) > 0) {
    92105            const loadBuildId = Number(urlBuildId);
    93             onGetBuildComponents({ buildId: loadBuildId })
    94                 .then(async (components) => {
    95                     if (components && components.length > 0) {
     106
     107            onGetBuildState({ buildId: loadBuildId })
     108                .then((buildState) => {
     109                    if (buildState) {
    96110                        setBuildId(loadBuildId);
    97                         setBuildName("Cloned Build");
    98                         setDescription("");
    99 
    100                         const detailedComponents = await Promise.all(
    101                             components.map(async (c: any) => {
    102                                 const full = await onGetComponentDetails({ componentId: c.id }).catch(() => null);
    103                                 return full ? { ...c, ...full, details: full?.details } : c;
    104                             })
    105                         );
    106 
    107                         const componentMap = new Map();
    108                         detailedComponents.forEach((c: any) => componentMap.set(c.type, c));
    109 
    110                         setSlots(prevSlots => prevSlots.map(slot => {
    111                             const match = componentMap.get(slot.type);
    112                             return match ? { ...slot, component: match } : slot;
    113                         }));
    114 
    115                         window.history.replaceState({}, document.title, "/forge");
     111                        setBuildName(buildState.build.name);
     112                        setDescription(buildState.build.description || "");
    116113                    }
    117114                })
    118                 .catch(() => {});
     115                .catch(() => {})
     116                .finally(() => {
     117                    onGetBuildComponents({ buildId: loadBuildId })
     118                        .then(async (components) => {
     119                            if (components && components.length > 0) {
     120                                const detailedComponents = await Promise.all(
     121                                    components.map(async (c: any) => {
     122                                        const full = await onGetComponentDetails({ componentId: c.id }).catch(() => null);
     123                                        return full ? { ...c, ...full, details: full?.details } : c;
     124                                    })
     125                                );
     126
     127                                const componentMap = new Map();
     128                                detailedComponents.forEach((c: any) => componentMap.set(c.type, c));
     129
     130                                setSlots(prevSlots => prevSlots.map(slot => {
     131                                    const match = componentMap.get(slot.type);
     132                                    return match ? { ...slot, component: match } : slot;
     133                                }));
     134
     135                                window.history.replaceState({}, document.title, "/forge");
     136                            }
     137                        })
     138                        .catch(() => {});
     139                });
    119140        }
    120141    }, []);
     
    159180    };
    160181
    161 
    162182    const handleRemovePart = async (slotId: string) => {
    163183        const slot = slots.find(s => s.id === slotId);
     
    199219    };
    200220
    201     const handleSubmit = async () => {
     221    const handleSubmit = () => {
    202222        if (!buildName.trim()) return alert("Please name your build!");
    203223        if (!buildId) return alert("You must add at least one component before submitting.");
    204224
     225        setTempDescription(description || "");
     226        setSubmitDialogOpen(true);
     227    };
     228
     229    const handleSubmitConfirm = async () => {
     230        if(!buildId) return;
     231
    205232        setIsSubmitting(true);
     233        setSubmitDialogOpen(false);
     234
    206235        try {
     236            await saveBuildState({ buildId, name: buildName.trim(), description: tempDescription });
    207237            const result = await onEditBuild({buildId});
    208 
    209238            if (!result) throw new Error("Failed to save build");
    210239
     
    218247        }
    219248    };
    220 
    221249
    222250    const activeSlotType = useMemo(() => {
     
    410438                onClose={() => setDetailsOpen(null)}
    411439            />
     440
     441            <Dialog open={submitDialogOpen} onClose={() => setSubmitDialogOpen(false)} maxWidth="sm" fullWidth>
     442                <DialogTitle sx={{ bgcolor: '#ff8201', color: 'white', fontWeight: 'bold' }}>
     443                    Build Description
     444                </DialogTitle>
     445                <DialogContent sx={{ p: 3 }}>
     446                    <Typography variant="body1" sx={{ mb: 2, color: 'text.secondary' }}>
     447                        Add some notes about your build (optional):
     448                    </Typography>
     449                    <TextField
     450                        fullWidth
     451                        multiline
     452                        rows={4}
     453                        placeholder="e.g. Gaming build for 1440p, quiet operation, future-proof..."
     454                        value={tempDescription}
     455                        onChange={(e) => setTempDescription(e.target.value)}
     456                        variant="outlined"
     457                    />
     458                </DialogContent>
     459                <DialogActions sx={{ p: 3, pt: 0 }}>
     460                    <Button onClick={() => setSubmitDialogOpen(false)}>
     461                        Cancel
     462                    </Button>
     463                    <Button
     464                        variant="contained"
     465                        color="primary"
     466                        onClick={handleSubmitConfirm}
     467                        disabled={isSubmitting}
     468                    >
     469                        {isSubmitting ? (
     470                            <>
     471                                <CircularProgress size={20} sx={{ mr: 1 }} />
     472                                Submitting...
     473                            </>
     474                        ) : (
     475                            'Submit Build'
     476                        )}
     477                    </Button>
     478                </DialogActions>
     479            </Dialog>
    412480        </Container>
    413481    );
Note: See TracChangeset for help on using the changeset viewer.