This commit is contained in:
@@ -446,11 +446,10 @@ export const createProductAdmin = async (formData: FormData) => {
|
|||||||
`${V2}/admin/protected/products`,
|
`${V2}/admin/protected/products`,
|
||||||
formData,
|
formData,
|
||||||
{
|
{
|
||||||
headers: { "Content-Type": "multipart/form-data" },
|
|
||||||
timeout: 120000,
|
timeout: 120000,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return { success: true, data: data.data, message: data.message };
|
return { success: true, data: data.product, message: data.message };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateProductAdmin = async (
|
export const updateProductAdmin = async (
|
||||||
@@ -749,7 +748,7 @@ export const uploadProductMediaAdmin = async (
|
|||||||
const { data } = await apiClient.post(
|
const { data } = await apiClient.post(
|
||||||
`${V2}/admin/protected/products/${productId}/media`,
|
`${V2}/admin/protected/products/${productId}/media`,
|
||||||
fd,
|
fd,
|
||||||
{ headers: { "Content-Type": "multipart/form-data" }, timeout: 120000 },
|
{ timeout: 120000 },
|
||||||
);
|
);
|
||||||
return { success: true, media: data.media, message: data.message };
|
return { success: true, media: data.media, message: data.message };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -62,12 +62,12 @@ interface PendingMedia {
|
|||||||
// Les catégories sont chargées dynamiquement depuis l'API
|
// Les catégories sont chargées dynamiquement depuis l'API
|
||||||
|
|
||||||
const UNITS = [
|
const UNITS = [
|
||||||
{ value: "u", label: "u" },
|
{ value: "u", label: "u" },
|
||||||
{ value: "kg", label: "kg" },
|
{ value: "kg", label: "kg" },
|
||||||
{ value: "g", label: "g" },
|
{ value: "g", label: "g" },
|
||||||
{ value: "bag", label: "bag" },
|
{ value: "bag", label: "bag" },
|
||||||
{ value: "l", label: "l" },
|
{ value: "l", label: "l" },
|
||||||
{ value: "cl", label: "cl" },
|
{ value: "cl", label: "cl" },
|
||||||
{ value: "pcs", label: "pcs" },
|
{ value: "pcs", label: "pcs" },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -247,11 +247,7 @@ export default function ProductsScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await ImagePicker.launchImageLibraryAsync({
|
const result = await ImagePicker.launchImageLibraryAsync({
|
||||||
mediaTypes:
|
mediaTypes: type === "image" ? ["images"] : ["videos"],
|
||||||
type === "image"
|
|
||||||
? ImagePicker.MediaTypeOptions.Images
|
|
||||||
: ImagePicker.MediaTypeOptions.Videos,
|
|
||||||
quality: 0.8,
|
|
||||||
allowsMultipleSelection: true,
|
allowsMultipleSelection: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -358,7 +354,10 @@ export default function ProductsScreen() {
|
|||||||
prices.forEach((p, i) => {
|
prices.forEach((p, i) => {
|
||||||
fd.append(`prices[${i}][quantity]`, String(p.quantity));
|
fd.append(`prices[${i}][quantity]`, String(p.quantity));
|
||||||
fd.append(`prices[${i}][price]`, String(p.price));
|
fd.append(`prices[${i}][price]`, String(p.price));
|
||||||
fd.append(`prices[${i}][active_price]`, p.active_price ? "true" : "false");
|
fd.append(
|
||||||
|
`prices[${i}][active_price]`,
|
||||||
|
p.active_price ? "true" : "false",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Attacher les médias en attente
|
// Attacher les médias en attente
|
||||||
@@ -388,13 +387,18 @@ export default function ProductsScreen() {
|
|||||||
m.mediaType,
|
m.mediaType,
|
||||||
);
|
);
|
||||||
} catch (uploadErr: any) {
|
} catch (uploadErr: any) {
|
||||||
const msg = uploadErr?.response?.data?.error || uploadErr?.message || `Erreur upload ${m.mediaType}`;
|
const msg =
|
||||||
|
uploadErr?.response?.data?.error ||
|
||||||
|
uploadErr?.message ||
|
||||||
|
`Erreur upload ${m.mediaType}`;
|
||||||
uploadErrors.push(msg);
|
uploadErrors.push(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setUploadingMedia(false);
|
setUploadingMedia(false);
|
||||||
if (uploadErrors.length > 0) {
|
if (uploadErrors.length > 0) {
|
||||||
setFormError(`Erreur upload média: ${uploadErrors.join(", ")}`);
|
setFormError(
|
||||||
|
`Erreur upload média: ${uploadErrors.join(", ")}`,
|
||||||
|
);
|
||||||
await loadData();
|
await loadData();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -645,8 +649,14 @@ export default function ProductsScreen() {
|
|||||||
borderColor: "#22c55e",
|
borderColor: "#22c55e",
|
||||||
backgroundColor: "#22c55e20",
|
backgroundColor: "#22c55e20",
|
||||||
},
|
},
|
||||||
comingSoonBtnText: { color: colors.textMuted, fontSize: fontSize.sm },
|
comingSoonBtnText: {
|
||||||
comingSoonBtnTextActive: { color: "#22c55e", fontWeight: "700" },
|
color: colors.textMuted,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
},
|
||||||
|
comingSoonBtnTextActive: {
|
||||||
|
color: "#22c55e",
|
||||||
|
fontWeight: "700",
|
||||||
|
},
|
||||||
|
|
||||||
// Prices
|
// Prices
|
||||||
sectionHeader: {
|
sectionHeader: {
|
||||||
@@ -808,7 +818,10 @@ export default function ProductsScreen() {
|
|||||||
<Text style={styles.name}>{item.name}</Text>
|
<Text style={styles.name}>{item.name}</Text>
|
||||||
<Badge
|
<Badge
|
||||||
label={item.category}
|
label={item.category}
|
||||||
color={categories.find(c => c.name === item.category)?.color || colors.accent}
|
color={
|
||||||
|
categories.find((c) => c.name === item.category)
|
||||||
|
?.color || colors.accent
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -843,9 +856,18 @@ export default function ProductsScreen() {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<Text style={styles.info}>Stock: {item.stock} {item.unit || "u"}</Text>
|
<Text style={styles.info}>
|
||||||
|
Stock: {item.stock} {item.unit || "u"}
|
||||||
|
</Text>
|
||||||
{item.prices && item.prices.length > 0 && (
|
{item.prices && item.prices.length > 0 && (
|
||||||
<View style={{ flexDirection: "row", flexWrap: "wrap", gap: 4, marginTop: 2 }}>
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
gap: 4,
|
||||||
|
marginTop: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
{item.prices.map((p, i) => (
|
{item.prices.map((p, i) => (
|
||||||
<Text
|
<Text
|
||||||
key={i}
|
key={i}
|
||||||
@@ -858,7 +880,8 @@ export default function ProductsScreen() {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{p.quantity}{item.unit || "u"} = {p.price}€
|
{p.quantity}
|
||||||
|
{item.unit || "u"} = {p.price}€
|
||||||
{i < item.prices!.length - 1 ? " |" : ""}
|
{i < item.prices!.length - 1 ? " |" : ""}
|
||||||
</Text>
|
</Text>
|
||||||
))}
|
))}
|
||||||
@@ -1024,7 +1047,8 @@ export default function ProductsScreen() {
|
|||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[
|
style={[
|
||||||
styles.comingSoonBtn,
|
styles.comingSoonBtn,
|
||||||
form.comingSoon && styles.comingSoonBtnActive,
|
form.comingSoon &&
|
||||||
|
styles.comingSoonBtnActive,
|
||||||
]}
|
]}
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
setForm((f) => {
|
setForm((f) => {
|
||||||
@@ -1032,16 +1056,24 @@ export default function ProductsScreen() {
|
|||||||
return {
|
return {
|
||||||
...f,
|
...f,
|
||||||
comingSoon: next,
|
comingSoon: next,
|
||||||
prices: f.prices.map((p) => ({ ...p, active: !next })),
|
prices: f.prices.map((p) => ({
|
||||||
|
...p,
|
||||||
|
active: !next,
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Text style={[
|
<Text
|
||||||
styles.comingSoonBtnText,
|
style={[
|
||||||
form.comingSoon && styles.comingSoonBtnTextActive,
|
styles.comingSoonBtnText,
|
||||||
]}>
|
form.comingSoon &&
|
||||||
{form.comingSoon ? "À venir (activé)" : "Marquer comme «À venir»"}
|
styles.comingSoonBtnTextActive,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{form.comingSoon
|
||||||
|
? "À venir (activé)"
|
||||||
|
: "Marquer comme «À venir»"}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
@@ -1140,9 +1172,18 @@ export default function ProductsScreen() {
|
|||||||
onPress={() => togglePriceActive(idx)}
|
onPress={() => togglePriceActive(idx)}
|
||||||
>
|
>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name={p.active ? "checkmark-circle" : "close-circle"}
|
name={
|
||||||
|
p.active
|
||||||
|
? "checkmark-circle"
|
||||||
|
: "close-circle"
|
||||||
|
}
|
||||||
size={22}
|
size={22}
|
||||||
color={p.active ? colors.success || "#22c55e" : colors.danger}
|
color={
|
||||||
|
p.active
|
||||||
|
? colors.success ||
|
||||||
|
"#22c55e"
|
||||||
|
: colors.danger
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{form.prices.length > 1 && (
|
{form.prices.length > 1 && (
|
||||||
|
|||||||
Reference in New Issue
Block a user