Files
siop2/apps/mobile/app/bibliotheque/index.tsx
pr-daaif f210d4f801 feat(r6): R6.3 — Ressources sur mobile (Stock, Tiers, Fichiers)
api/ressources.ts (usePartners, useParts/usePart, useCreatePurchaseOrder,
useDocuments). Écran Stock (sous-seuil en tête) + fiche pièce + "Commander"
pré-rempli en une ligne (fournisseur figé, quantité = manquant jusqu'au
seuil, prix = dernier connu — BC multi-lignes détaillé réservé au web, D4).
Tiers en lecture seule (création/édition réservées au web). Fichiers en
métadonnées seules — l'ouverture demande expo-sharing (dépendance native
absente, donc un nouveau build natif) : différée explicitement plutôt
qu'ajoutée à la légère au milieu de cette passe.

Menu : Stock & achats / Tiers / Fichiers routent réellement.

Typecheck propre, 17 tests Jest, lint 5/5 paquets. Contrat non touché,
toutes les opérations utilisées existaient déjà depuis R3.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 11:35:55 +01:00

81 lines
3.1 KiB
TypeScript

import { FlatList, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useDocuments } from '@/api/ressources';
import { EnteteFiche } from '@/composants/ui';
import { useTokens } from '@/theme/tokens';
const ICONE_TYPE: Record<string, string> = {
NOTICE: '📘',
CERTIFICATE: '📜',
PHOTO: '🖼',
OTHER: '📄',
};
function taille(octets: number): string {
if (octets < 1024) return `${octets} o`;
if (octets < 1024 * 1024) return `${Math.round(octets / 1024)} Ko`;
return `${(octets / (1024 * 1024)).toFixed(1)} Mo`;
}
/** Fichiers — R6.3 (Ressources). Consultation des métadonnées seulement
* (D4) : l'ouverture/téléchargement d'un document sur mobile demande un
* flux authentifié (l'API le streame, MinIO n'est jamais exposé) suivi
* d'un partage natif — nécessite `expo-sharing`, pas encore une dépendance
* du projet ; ajoutée dans une prochaine étape plutôt que d'introduire une
* nouvelle dépendance native (et donc un nouveau build) dans cette passe.
* En attendant : ouvrir depuis le web. */
export default function PageBibliotheque() {
const t = useTokens();
const { data: documents } = useDocuments();
const fichiers = [...(documents ?? [])].sort(
(a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt),
);
return (
<SafeAreaView style={{ flex: 1, backgroundColor: t.fond }} edges={['top']}>
<View style={{ flex: 1, padding: 14, gap: 10 }}>
<EnteteFiche titre="Fichiers" />
<Text style={{ fontFamily: 'Manrope_600SemiBold', fontSize: 11.5, color: t.encre3 }}>
Consultation seulement l'ouverture se fait depuis le web pour l'instant.
</Text>
<FlatList
data={fichiers}
keyExtractor={(d) => d.id}
contentContainerStyle={{ gap: 8, paddingBottom: 12 }}
ListEmptyComponent={
<Text style={{ color: t.encre3, fontFamily: 'Manrope_600SemiBold', padding: 16, textAlign: 'center' }}>
Aucun document accessible.
</Text>
}
renderItem={({ item: d }) => (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
gap: 10,
backgroundColor: t.surface,
borderColor: t.bordure,
borderWidth: 1,
borderRadius: 12,
padding: 12,
}}
>
<Text style={{ fontSize: 20 }}>{ICONE_TYPE[d.kind] ?? '📄'}</Text>
<View style={{ flex: 1, gap: 1 }}>
<Text numberOfLines={1} style={{ fontFamily: 'Manrope_700Bold', fontSize: 13, color: t.encre }}>
{d.fileName}
</Text>
<Text style={{ fontFamily: 'Manrope_400Regular', fontSize: 11.5, color: t.encre2 }}>
{[d.assetReference && `Asc. ${d.assetReference}`, d.workOrderReference, taille(d.size)]
.filter(Boolean)
.join(' · ')}
</Text>
</View>
</View>
)}
/>
</View>
</SafeAreaView>
);
}