// Primus IQ — SharePoint Picker Modal const spFmtSize = (bytes) => { const b = bytes || 0; return b < 1024 ? `${b} B` : b < 1048576 ? `${(b / 1024).toFixed(1)} KB` : `${(b / 1048576).toFixed(1)} MB`; }; const SharePointPickerModal = ({ open, onClose, onConfirm }) => { const [tab, setTab] = React.useState('onedrive'); // 'onedrive' | 'sharepoint' const [siteQuery, setSiteQuery] = React.useState(''); const [sites, setSites] = React.useState([]); const [selectedSite, setSelectedSite] = React.useState(null); const [drives, setDrives] = React.useState([]); const [drive, setDrive] = React.useState(null); // active drive being browsed const [path, setPath] = React.useState([]); // breadcrumb: [{id, name}] const [items, setItems] = React.useState([]); const [selected, setSelected] = React.useState({}); // itemId -> {drive_id, item_id, name, size} const [loading, setLoading] = React.useState(false); const [error, setError] = React.useState(''); const fail = (ex) => { setError(ex && ex.message ? ex.message : 'Something went wrong'); setLoading(false); }; // ── OneDrive: open the user's drive directly ── const openOneDrive = async () => { setTab('onedrive'); setSelectedSite(null); setDrives([]); setSites([]); setSiteQuery(''); setError(''); setLoading(true); try { const d = await PrimusAPI.spOneDrive(); setDrive(d); setPath([{ id: null, name: d.name || 'OneDrive' }]); const its = await PrimusAPI.spListItems(d.id, null); setItems(its || []); setLoading(false); } catch (ex) { fail(ex); } }; // ── SharePoint: switch tab and auto-load accessible sites ── const switchToSharePoint = async () => { setTab('sharepoint'); setDrive(null); setSelectedSite(null); setDrives([]); setPath([]); setItems([]); setError(''); setSites([]); setLoading(true); try { const res = await PrimusAPI.spSearchSites(siteQuery); setSites(res || []); setLoading(false); } catch (ex) { fail(ex); } }; // ── SharePoint: refine site search ── const runSiteSearch = async () => { setLoading(true); setError(''); try { const res = await PrimusAPI.spSearchSites(siteQuery); setSites(res || []); setLoading(false); } catch (ex) { fail(ex); } }; // Auto-load OneDrive when modal opens. Reset selection + breadcrumb so a fresh open // never carries over the previously imported file's selection. React.useEffect(() => { if (open) { setSelected({}); setPath([]); openOneDrive(); } }, [open]); const pickSite = async (site) => { setSelectedSite(site); setDrive(null); setPath([]); setItems([]); setError(''); setLoading(true); try { const ds = await PrimusAPI.spListDrives(site.id); setDrives(ds || []); setLoading(false); } catch (ex) { fail(ex); } }; const pickDrive = async (d) => { setDrive(d); setPath([{ id: null, name: d.name }]); setError(''); setLoading(true); try { const its = await PrimusAPI.spListItems(d.id, null); setItems(its || []); setLoading(false); } catch (ex) { fail(ex); } }; const openFolder = async (folder) => { setError(''); setLoading(true); try { const its = await PrimusAPI.spListItems(drive.id, folder.id); setPath(prev => [...prev, { id: folder.id, name: folder.name }]); setItems(its || []); setLoading(false); } catch (ex) { fail(ex); } }; const goToCrumb = async (idx) => { const crumb = path[idx]; setError(''); setLoading(true); try { const its = await PrimusAPI.spListItems(drive.id, crumb.id); setPath(prev => prev.slice(0, idx + 1)); setItems(its || []); setLoading(false); } catch (ex) { fail(ex); } }; const toggleFile = (item) => { setSelected(prev => { const next = { ...prev }; if (next[item.id]) delete next[item.id]; else next[item.id] = { drive_id: drive.id, item_id: item.id, name: item.name, size: item.size }; return next; }); }; const selectedList = Object.values(selected); const confirm = () => { if (selectedList.length === 0) return; onConfirm(selectedList); }; if (!open) return null; const showBrowser = !!drive; const showSiteList = tab === 'sharepoint' && !selectedSite; const showDriveList = tab === 'sharepoint' && selectedSite && !drive; return (