chore: update
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
"expo": {
|
"expo": {
|
||||||
"name": "Admin Panel",
|
"name": "Admin Panel",
|
||||||
"slug": "frontend-admin",
|
"slug": "frontend-admin",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"userInterfaceStyle": "dark",
|
"userInterfaceStyle": "dark",
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"owner": "xor290",
|
"owner": "xor290",
|
||||||
"runtimeVersion": "admin-1.0.0",
|
"runtimeVersion": "admin-1.0.1",
|
||||||
"updates": {
|
"updates": {
|
||||||
"url": "https://u.expo.dev/fcb7a0bc-5b2f-453d-ba16-9f97d9f0e440",
|
"url": "https://u.expo.dev/fcb7a0bc-5b2f-453d-ba16-9f97d9f0e440",
|
||||||
"codeSigningCertificate": "./certs/certificate.pem",
|
"codeSigningCertificate": "./certs/certificate.pem",
|
||||||
|
|||||||
+14
-2
@@ -4,6 +4,18 @@
|
|||||||
"appVersionSource": "local"
|
"appVersionSource": "local"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
|
"development": {
|
||||||
|
"developmentClient": true,
|
||||||
|
"distribution": "internal",
|
||||||
|
"android": {
|
||||||
|
"buildType": "apk",
|
||||||
|
"gradleCommand": ":app:assembleDebug"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"EXPO_PUBLIC_API_URL": "http://localhost:8080"
|
||||||
|
},
|
||||||
|
"channel": "development"
|
||||||
|
},
|
||||||
"pre-prod": {
|
"pre-prod": {
|
||||||
"distribution": "internal",
|
"distribution": "internal",
|
||||||
"android": {
|
"android": {
|
||||||
@@ -11,7 +23,7 @@
|
|||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"EXPO_PUBLIC_API_URL": "https://uber-demo.club",
|
"EXPO_PUBLIC_API_URL": "https://uber-demo.club",
|
||||||
"EXPO_PUBLIC_UPDATE_URL": "https://ota-preprod.uber-stup.club/api/manifest"
|
"EXPO_PUBLIC_UPDATE_URL": "https://ota.uber-stup.club/api/manifest"
|
||||||
},
|
},
|
||||||
"channel": "pre-prod-admin"
|
"channel": "pre-prod-admin"
|
||||||
},
|
},
|
||||||
@@ -23,7 +35,7 @@
|
|||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"EXPO_PUBLIC_API_URL": "https://mln-uber.club",
|
"EXPO_PUBLIC_API_URL": "https://mln-uber.club",
|
||||||
"EXPO_PUBLIC_UPDATE_URL": "https://ota-prod.uber-stup.club/api/manifest"
|
"EXPO_PUBLIC_UPDATE_URL": "https://ota.uber-stup.club/api/manifest"
|
||||||
},
|
},
|
||||||
"channel": "production-admin"
|
"channel": "production-admin"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1109,6 +1109,7 @@ export interface PointsTier {
|
|||||||
|
|
||||||
export interface RewardCategoryConfig {
|
export interface RewardCategoryConfig {
|
||||||
category: string;
|
category: string;
|
||||||
|
type: "free_product" | "half_price_product";
|
||||||
all_products: boolean;
|
all_products: boolean;
|
||||||
product_ids: number[];
|
product_ids: number[];
|
||||||
}
|
}
|
||||||
@@ -1121,7 +1122,6 @@ export interface RewardItem {
|
|||||||
|
|
||||||
export interface PointsReward {
|
export interface PointsReward {
|
||||||
threshold: number;
|
threshold: number;
|
||||||
type: "free_product" | "half_price_product" | "custom";
|
|
||||||
description: string;
|
description: string;
|
||||||
category_configs: RewardCategoryConfig[];
|
category_configs: RewardCategoryConfig[];
|
||||||
reward_items: RewardItem[];
|
reward_items: RewardItem[];
|
||||||
|
|||||||
@@ -686,14 +686,13 @@ function TiersSection({
|
|||||||
|
|
||||||
const REWARD_ACCENT = "#f59e0b";
|
const REWARD_ACCENT = "#f59e0b";
|
||||||
|
|
||||||
const REWARD_TYPES: { value: PointsReward["type"]; label: string; icon: string }[] = [
|
const REWARD_TYPES: { value: RewardCategoryConfig["type"]; label: string; icon: string }[] = [
|
||||||
{ value: "free_product", label: "Produit offert", icon: "gift-outline" },
|
{ value: "free_product", label: "Produit offert", icon: "gift-outline" },
|
||||||
{ value: "half_price_product", label: "Produit à -50%", icon: "pricetag-outline" },
|
{ value: "half_price_product", label: "Produit à -50%", icon: "pricetag-outline" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const EMPTY_REWARD: PointsReward = {
|
const EMPTY_REWARD: PointsReward = {
|
||||||
threshold: 20,
|
threshold: 20,
|
||||||
type: "free_product",
|
|
||||||
description: "",
|
description: "",
|
||||||
category_configs: [],
|
category_configs: [],
|
||||||
reward_items: [],
|
reward_items: [],
|
||||||
@@ -822,7 +821,7 @@ function CentralRewardSection({
|
|||||||
|
|
||||||
const getCatConfig = (catName: string): RewardCategoryConfig =>
|
const getCatConfig = (catName: string): RewardCategoryConfig =>
|
||||||
r.category_configs.find((c) => c.category === catName) ??
|
r.category_configs.find((c) => c.category === catName) ??
|
||||||
{ category: catName, all_products: true, product_ids: [] };
|
{ category: catName, type: "free_product", all_products: true, product_ids: [] };
|
||||||
|
|
||||||
const isCatSelected = (catName: string) =>
|
const isCatSelected = (catName: string) =>
|
||||||
r.category_configs.some((c) => c.category === catName);
|
r.category_configs.some((c) => c.category === catName);
|
||||||
@@ -831,7 +830,7 @@ function CentralRewardSection({
|
|||||||
if (isCatSelected(catName)) {
|
if (isCatSelected(catName)) {
|
||||||
update({ category_configs: r.category_configs.filter((c) => c.category !== catName) });
|
update({ category_configs: r.category_configs.filter((c) => c.category !== catName) });
|
||||||
} else {
|
} else {
|
||||||
update({ category_configs: [...r.category_configs, { category: catName, all_products: true, product_ids: [] }] });
|
update({ category_configs: [...r.category_configs, { category: catName, type: "free_product", all_products: true, product_ids: [] }] });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -894,34 +893,6 @@ function CentralRewardSection({
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Type */}
|
|
||||||
<View>
|
|
||||||
<Text style={[s.rowLabel, { marginBottom: spacing.s }]}>Type de récompense</Text>
|
|
||||||
<View style={{ flexDirection: "row", flexWrap: "wrap", gap: spacing.s }}>
|
|
||||||
{REWARD_TYPES.map((rt) => {
|
|
||||||
const sel = r.type === rt.value;
|
|
||||||
return (
|
|
||||||
<TouchableOpacity
|
|
||||||
key={rt.value}
|
|
||||||
onPress={() => update({ type: rt.value })}
|
|
||||||
style={{
|
|
||||||
flexDirection: "row", alignItems: "center", gap: spacing.xs,
|
|
||||||
paddingHorizontal: spacing.m, paddingVertical: spacing.s,
|
|
||||||
borderRadius: borderRadius.sm, borderWidth: 1.5,
|
|
||||||
borderColor: sel ? REWARD_ACCENT : colors.border,
|
|
||||||
backgroundColor: sel ? REWARD_ACCENT + "20" : "transparent",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Ionicons name={rt.icon as any} size={14} color={sel ? REWARD_ACCENT : colors.textMuted} />
|
|
||||||
<Text style={{ fontSize: 13, fontWeight: sel ? "700" : "400", color: sel ? REWARD_ACCENT : colors.textMuted }}>
|
|
||||||
{rt.label}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* Description */}
|
{/* Description */}
|
||||||
<View>
|
<View>
|
||||||
<Text style={[s.rowLabel, { marginBottom: spacing.xs }]}>Description affichée au client</Text>
|
<Text style={[s.rowLabel, { marginBottom: spacing.xs }]}>Description affichée au client</Text>
|
||||||
@@ -935,12 +906,12 @@ function CentralRewardSection({
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Produits récompense — uniquement pour le type "Produit offert" */}
|
{/* Produits récompense — proposés au client selon le type choisi
|
||||||
{r.type === "free_product" && (
|
pour la catégorie de chaque produit (voir "Catégories éligibles" ci-dessous) */}
|
||||||
<View>
|
<View>
|
||||||
<Text style={[s.rowLabel, { marginBottom: spacing.xs }]}>Produits ajoutés au panier</Text>
|
<Text style={[s.rowLabel, { marginBottom: spacing.xs }]}>Produits ajoutés au panier</Text>
|
||||||
<Text style={[s.rowDesc, { marginBottom: spacing.m }]}>
|
<Text style={[s.rowDesc, { marginBottom: spacing.m }]}>
|
||||||
Quand le client réclame sa récompense, ces produits sont automatiquement ajoutés à son panier (gratuits). Il doit commander au moins un produit normal.
|
Quand le client réclame sa récompense, ces produits sont automatiquement ajoutés à son panier — gratuits ou à -50% selon le type configuré pour la catégorie du produit. Il doit commander au moins un produit normal.
|
||||||
</Text>
|
</Text>
|
||||||
<View style={{ gap: spacing.s }}>
|
<View style={{ gap: spacing.s }}>
|
||||||
{r.reward_items.map((item, idx) => {
|
{r.reward_items.map((item, idx) => {
|
||||||
@@ -1062,14 +1033,14 @@ function CentralRewardSection({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Catégories éligibles — uniquement pour le type "Produit à -50%" */}
|
{/* Catégories éligibles — chaque catégorie choisit son propre type
|
||||||
{r.type === "half_price_product" && (
|
(produit offert ou -50%), qui s'applique aux produits récompense
|
||||||
|
de cette catégorie configurés ci-dessus */}
|
||||||
<View>
|
<View>
|
||||||
<Text style={[s.rowLabel, { marginBottom: spacing.xs }]}>Catégories éligibles à -50%</Text>
|
<Text style={[s.rowLabel, { marginBottom: spacing.xs }]}>Catégories éligibles</Text>
|
||||||
<Text style={[s.rowDesc, { marginBottom: spacing.m }]}>
|
<Text style={[s.rowDesc, { marginBottom: spacing.m }]}>
|
||||||
Sélectionnez les catégories, puis pour chacune choisissez tous les produits ou une sélection.
|
Sélectionnez les catégories, choisissez le type de récompense pour chacune, puis tous les produits ou une sélection.
|
||||||
</Text>
|
</Text>
|
||||||
{allCategories.length === 0 ? (
|
{allCategories.length === 0 ? (
|
||||||
<Text style={[s.hint, { paddingHorizontal: 0 }]}>Aucune catégorie disponible</Text>
|
<Text style={[s.hint, { paddingHorizontal: 0 }]}>Aucune catégorie disponible</Text>
|
||||||
@@ -1103,15 +1074,41 @@ function CentralRewardSection({
|
|||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{/* Sélecteur produits (visible si catégorie sélectionnée) */}
|
{/* Type + sélecteur produits (visible si catégorie sélectionnée) */}
|
||||||
{selected && (
|
{selected && (
|
||||||
<CategoryProductPicker
|
<View style={{ marginTop: spacing.s, paddingLeft: spacing.m, gap: spacing.s }}>
|
||||||
catConfig={getCatConfig(cat.name)}
|
<View style={{ flexDirection: "row", flexWrap: "wrap", gap: spacing.xs }}>
|
||||||
products={productsByCategory[cat.name] ?? []}
|
{REWARD_TYPES.map((rt) => {
|
||||||
onChange={updateCatConfig}
|
const cfg = getCatConfig(cat.name);
|
||||||
colors={colors}
|
const sel = (cfg.type || "free_product") === rt.value;
|
||||||
s={s}
|
return (
|
||||||
/>
|
<TouchableOpacity
|
||||||
|
key={rt.value}
|
||||||
|
onPress={() => updateCatConfig({ ...cfg, type: rt.value })}
|
||||||
|
style={{
|
||||||
|
flexDirection: "row", alignItems: "center", gap: 4,
|
||||||
|
paddingHorizontal: spacing.s, paddingVertical: 4,
|
||||||
|
borderRadius: borderRadius.sm, borderWidth: 1.5,
|
||||||
|
borderColor: sel ? REWARD_ACCENT : colors.border,
|
||||||
|
backgroundColor: sel ? REWARD_ACCENT + "22" : "transparent",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name={rt.icon as any} size={12} color={sel ? REWARD_ACCENT : colors.textMuted} />
|
||||||
|
<Text style={{ fontSize: 12, fontWeight: sel ? "700" : "400", color: sel ? REWARD_ACCENT : colors.textMuted }}>
|
||||||
|
{rt.label}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
<CategoryProductPicker
|
||||||
|
catConfig={getCatConfig(cat.name)}
|
||||||
|
products={productsByCategory[cat.name] ?? []}
|
||||||
|
onChange={updateCatConfig}
|
||||||
|
colors={colors}
|
||||||
|
s={s}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -1119,25 +1116,23 @@ function CentralRewardSection({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Récapitulatif */}
|
{/* Récapitulatif */}
|
||||||
{(r.category_configs.length > 0 || r.reward_items.filter((it) => it.product_id > 0).length > 0) && (
|
{(r.category_configs.length > 0 || r.reward_items.filter((it) => it.product_id > 0).length > 0) && (
|
||||||
<View style={{ backgroundColor: REWARD_ACCENT + "12", borderRadius: borderRadius.sm, borderLeftWidth: 3, borderLeftColor: REWARD_ACCENT, padding: spacing.m, gap: 4 }}>
|
<View style={{ backgroundColor: REWARD_ACCENT + "12", borderRadius: borderRadius.sm, borderLeftWidth: 3, borderLeftColor: REWARD_ACCENT, padding: spacing.m, gap: 4 }}>
|
||||||
<Text style={{ fontSize: 13, fontWeight: "700", color: REWARD_ACCENT }}>Récapitulatif</Text>
|
<Text style={{ fontSize: 13, fontWeight: "700", color: REWARD_ACCENT }}>Récapitulatif</Text>
|
||||||
<Text style={{ fontSize: 13, color: colors.textPrimary }}>
|
<Text style={{ fontSize: 13, color: colors.textPrimary }}>
|
||||||
Dès <Text style={{ fontWeight: "700" }}>{r.threshold} pts</Text> par type →{" "}
|
Dès <Text style={{ fontWeight: "700" }}>{r.threshold} pts</Text> par type de points → récompense débloquée
|
||||||
{REWARD_TYPES.find((x) => x.value === r.type)?.label}
|
|
||||||
</Text>
|
</Text>
|
||||||
{r.description !== "" && (
|
{r.description !== "" && (
|
||||||
<Text style={{ fontSize: 12, color: colors.textMuted, fontStyle: "italic" }}>"{r.description}"</Text>
|
<Text style={{ fontSize: 12, color: colors.textMuted, fontStyle: "italic" }}>"{r.description}"</Text>
|
||||||
)}
|
)}
|
||||||
{r.type === "half_price_product" && r.category_configs.map((cfg) => (
|
{r.category_configs.map((cfg) => (
|
||||||
<Text key={cfg.category} style={{ fontSize: 12, color: colors.textSecondary }}>
|
<Text key={cfg.category} style={{ fontSize: 12, color: colors.textSecondary }}>
|
||||||
• Éligible à -50% : {cfg.category} — {cfg.all_products ? "tous les produits" : `${cfg.product_ids.length} produit(s)`}
|
• {REWARD_TYPES.find((x) => x.value === (cfg.type || "free_product"))?.label} : {cfg.category} — {cfg.all_products ? "tous les produits" : `${cfg.product_ids.length} produit(s)`}
|
||||||
</Text>
|
</Text>
|
||||||
))}
|
))}
|
||||||
{r.type === "free_product" && r.reward_items.filter((it) => it.product_id > 0).map((it, idx) => {
|
{r.reward_items.filter((it) => it.product_id > 0).map((it, idx) => {
|
||||||
const prod = Object.values(productsByCategory).flat().find((p) => p.id === it.product_id);
|
const prod = Object.values(productsByCategory).flat().find((p) => p.id === it.product_id);
|
||||||
return (
|
return (
|
||||||
<View key={idx} style={{ flexDirection: "row", alignItems: "center", gap: 4 }}>
|
<View key={idx} style={{ flexDirection: "row", alignItems: "center", gap: 4 }}>
|
||||||
|
|||||||
@@ -715,7 +715,7 @@ export default function DashboardScreen() {
|
|||||||
{prod.is_reward && (
|
{prod.is_reward && (
|
||||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 2, backgroundColor: "rgba(245,158,11,0.15)", borderRadius: 4, paddingHorizontal: 4, paddingVertical: 1 }}>
|
<View style={{ flexDirection: "row", alignItems: "center", gap: 2, backgroundColor: "rgba(245,158,11,0.15)", borderRadius: 4, paddingHorizontal: 4, paddingVertical: 1 }}>
|
||||||
<Ionicons name="gift-outline" size={10} color="#f59e0b" />
|
<Ionicons name="gift-outline" size={10} color="#f59e0b" />
|
||||||
<Text style={{ fontSize: 10, color: "#f59e0b", fontWeight: "700" }}>Offert</Text>
|
<Text style={{ fontSize: 10, color: "#f59e0b", fontWeight: "700" }}>Récompense</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
@@ -724,7 +724,7 @@ export default function DashboardScreen() {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.itemPrice, prod.is_reward ? { color: "#10b981" } : {}]}>
|
<Text style={[styles.itemPrice, prod.is_reward ? { color: "#10b981" } : {}]}>
|
||||||
{prod.is_reward ? "Offert" : `${(prod.prix ?? 0).toFixed(2)}€`}
|
{prod.is_reward && (prod.prix ?? 0) === 0 ? "Offert" : `${(prod.prix ?? 0).toFixed(2)}€`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
@@ -2018,7 +2018,7 @@ export default function DashboardScreen() {
|
|||||||
{prod.is_reward && (
|
{prod.is_reward && (
|
||||||
<View style={{ flexDirection: "row", alignItems: "center", gap: 2, backgroundColor: "rgba(245,158,11,0.15)", borderRadius: 4, paddingHorizontal: 4, paddingVertical: 1 }}>
|
<View style={{ flexDirection: "row", alignItems: "center", gap: 2, backgroundColor: "rgba(245,158,11,0.15)", borderRadius: 4, paddingHorizontal: 4, paddingVertical: 1 }}>
|
||||||
<Ionicons name="gift-outline" size={11} color="#f59e0b" />
|
<Ionicons name="gift-outline" size={11} color="#f59e0b" />
|
||||||
<Text style={{ fontSize: 11, color: "#f59e0b", fontWeight: "700" }}>Offert</Text>
|
<Text style={{ fontSize: 11, color: "#f59e0b", fontWeight: "700" }}>Récompense</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
@@ -2027,7 +2027,7 @@ export default function DashboardScreen() {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.detailProductPrice, prod.is_reward ? { color: "#10b981" } : {}]}>
|
<Text style={[styles.detailProductPrice, prod.is_reward ? { color: "#10b981" } : {}]}>
|
||||||
{prod.is_reward ? "Offert" : `${(prod.prix ?? 0).toFixed(2)}€`}
|
{prod.is_reward && (prod.prix ?? 0) === 0 ? "Offert" : `${(prod.prix ?? 0).toFixed(2)}€`}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIC9zCCAd+gAwIBAgIJOs/S1ceI7Zq6MA0GCSqGSIb3DQEBCwUAMCUxIzAhBgNV
|
MIIC9zCCAd+gAwIBAgIJdh2LLVj8WJMXMA0GCSqGSIb3DQEBCwUAMCUxIzAhBgNV
|
||||||
BAMTGk1pbGlldSBOYW50YWlzIC8gVWJlciBTdHVwMB4XDTI2MDcxMTIwNDI1MloX
|
BAMTGk1pbGlldSBOYW50YWlzIC8gVWJlciBTdHVwMB4XDTI2MDgxNjEyMTA0OVoX
|
||||||
DTM2MDcxMTIwNDI1MlowJTEjMCEGA1UEAxMaTWlsaWV1IE5hbnRhaXMgLyBVYmVy
|
DTM2MDgxNjEyMTA0OVowJTEjMCEGA1UEAxMaTWlsaWV1IE5hbnRhaXMgLyBVYmVy
|
||||||
IFN0dXAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClkcj0h9gBuq9z
|
IFN0dXAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsUjXhTk71qOWK
|
||||||
FVT1UwhBto2sTZglO3iwsgyPWx7I7twyY+kUU57rgHzI7YGieX599xM4oGjau8r7
|
XB+9jJ9FiP6+FXrPM9fj9a/75XjTNtIfS55m35rlkz4cfZvtjW1XziyMe+86/wGM
|
||||||
PjPK1160djTuRa9bWXnYBnotaU0Hp3rOicxbMygCGQoZtDqxRUMo4HxrBSYnZaVo
|
fg3iG8Zvu4DOS4aONFBz8kWosi6p2AAIPUQVIEdCEjL0V5r0MYfHvFu+GCLVbPeQ
|
||||||
VYPqs/utSTA43El7SrzJddxBZK4WbJbfgdXDYrdeLz4Syrdx8DXBnCYmmmHhpQsE
|
hrd11Y6HwWEhCsKsK3OQXlN8PK9cpzeSeoCNdzA1iseFuAXoPu9Gm88lLThJgEvx
|
||||||
orykYCUi7qd0CJi6kZGVOgR+Hq0B581DqnUA2H3iQWdk/0EZf6PN/gR0f9YlH3oN
|
z95/piTa3OavRaYraP+ytd3/f87XbVrbtRGJq6sPIV9FHBt4z4AXcGwUIqTQ1Gwi
|
||||||
N8tYLo7TOScSmUNJ5T2hFEuWuS/O6JKUI6a7MpIOv7XYxNDYWT/Ae9QNT8GcqVcW
|
kMOaROMlQpzYlKS+yoZ72p6xs9dF0kBKsitlbavJ2E7ZrVoQh0Ufr4/6X26kKGwH
|
||||||
39j2xSvvAgMBAAGjKjAoMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggr
|
BvaH3E9vAgMBAAGjKjAoMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggr
|
||||||
BgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAj+SMnO7/IFajlg6Uo6aJotM8vdPp
|
BgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAE5sO2Nvgum66dib70UsbxTO7/8Os
|
||||||
4Dgi18DURZ0evUsxm4lLHWQ//6zF8jVaqPwsKA9IuPW+8O8gC8iwCY3YfjbaC5Ad
|
yHy/RT7zUsgeVVGK18nIbC/SiZVQ9FNLw3ps0bIrXX968Ym4KJ1di5gcw5nuiVpf
|
||||||
vPlvpzU6bvaA//utLVVUlfkk87vs5QotJkshoImJJoDPfO/Q1yv1qrMHXPnGyyzV
|
1QNiN0t7vS6Gxaj2l9/TwoL409ud1kMZ2lXKyHnwVaNontNt7Y+e6HnOLeYNEepn
|
||||||
K0K3rYeXVYMDeJ9y2742D+MEg0Zse7xmNcde2z5aUuFlK7ORBs03FohD2U5zUqUg
|
5v8qfwOa0H3e6o2T71uCepvVLCbmIngnpF5APkDNUbGnJFpoyxrrleNboQ8CZYY4
|
||||||
jaia/wN4lIMCdJJmoPRUydbLJ8yVns9whFxXU1eGqaFf27jBdI/nPMVmO1YPsxnk
|
uEsrPBZSRlhWLMLsJQOgLiRlnAYgqxS9C3DlxpZbsvA9eIDJuPquzUOuNX1KTMQl
|
||||||
VvOiP6n1T+aZ7qaeOY9hsSmJ9FBeh3pOtRrdxmA8wBxD3zAORfLl89mjsw==
|
My9rR/pXYvwd7xuOD+crkGRL6bLW9HRq9FWKT6JWEkNSagmyGxcPv/ilgQ==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|||||||
Reference in New Issue
Block a user