diff --git a/public/images/pie-chart.png b/public/images/pie-chart.png index e9821fd..1809511 100644 Binary files a/public/images/pie-chart.png and b/public/images/pie-chart.png differ diff --git a/public/images/profile.png b/public/images/profile.png index 5e60eb7..f603980 100644 Binary files a/public/images/profile.png and b/public/images/profile.png differ diff --git a/public/images/sector.png b/public/images/sector.png index 6084390..bf926ae 100644 Binary files a/public/images/sector.png and b/public/images/sector.png differ diff --git a/public/images/supplier.png b/public/images/supplier.png index e152300..1d829a4 100644 Binary files a/public/images/supplier.png and b/public/images/supplier.png differ diff --git a/public/images/userpage.png b/public/images/userpage.png index a024e26..2407263 100644 Binary files a/public/images/userpage.png and b/public/images/userpage.png differ diff --git a/src/components/ProductCategory/ProductCategory.js b/src/components/ProductCategory/ProductCategory.js index 5859847..8f420c2 100644 --- a/src/components/ProductCategory/ProductCategory.js +++ b/src/components/ProductCategory/ProductCategory.js @@ -390,6 +390,7 @@ function ProductCategory(props) { props.onCategoryUpdated(props.categoryKey, categoryName, categoryImage) closeCategoryModal() + window.location.reload() flashInfo() } catch (err) { console.log(err) diff --git a/src/components/ProductCell/ProductCell.js b/src/components/ProductCell/ProductCell.js index 1949d39..d8d11cc 100644 --- a/src/components/ProductCell/ProductCell.js +++ b/src/components/ProductCell/ProductCell.js @@ -1,9 +1,41 @@ +import { useState, useEffect } from "react"; +import { useParams } from 'react-router-dom'; +import api from "../../services/api"; +import FlashMessage from '../../components/FlashMessage/FlashMessage'; +import ProductModal from "../ProductModal/ProductModal"; + const ProductCell = ({ aoClickar,product }) => { const onProductClick = () => { aoClickar(product.product_id); - - + } + + /** + * Renderização da flash message + */ + const [flash, setFlash] = useState(null) + + const showFlashMessage = (message, type) => { + setFlash(null) + setTimeout(() => { + setFlash({ message, type }) + }, 0) + } + + const flashSuccess = () => { + showFlashMessage('Item adicionado com sucesso!','success'); + } + + const flashError = () => { + showFlashMessage('Um erro aconteceu','error'); + }; + + const flashInfo = () => { + showFlashMessage('Item atualizado', 'info'); + } + + const flashDelete = () => { + showFlashMessage('Item deletado', 'success'); } const abbreviateNumber =(value,bool) => { @@ -22,20 +54,439 @@ const ProductCell = ({ aoClickar,product }) => { newValue += suffixes[suffixNum]; bool===true?bool='R$ ':bool=''; return bool + preffixes[suffixNum]+ ' ' + newValue; - } + } + /** + * Retorna todas as unidades + */ + const [units, setUnits] = useState([]) + + const fetchUnits = async () => { + try { + await api + .get('/unit') + .then(response => setUnits(response.data)) + } catch(err) { + console.log(err) + } + } + + /** + * Retorna todos os fornecedores + */ + + const [suppliers, setSuppliers] = useState([]) + + const fetchSuppliers = async () => { + try { + await api + .get('/supplier') + .then(response => setSuppliers(response.data)) + } catch(err) { + console.log(err) + } + } + /** + * Retorna todos os setores + */ + + const [sectors, setSector] = useState([]) + + const fetchSector = async () => { + try { + await api + .get('/sector') + .then(response => setSector(response.data)) + } catch(err) { + console.log(err) + } + } + + const [local, setLocals] = useState([]) + + const fetchLocals = async () => { + try { + await api + .get('/local') + .then(response => setLocals(response.data)) + } catch(err) { + console.log(err) + } + } + + /** + * Hook de useEffect para ativar as funções quando o componente é renderizado + */ + useEffect(() => { + const fetchData = async () => { + await fetchUnits() + await fetchSuppliers() + await fetchSector() + await fetchLocals() + } + fetchData() + }, []) + + const [isProdEditModalOpen, setIsProdEditModalOpen] = useState(false); + const [currentProduct, setCurrentProduct] = useState(null); + const parseCurrencyToFloat = (value) => { + return parseFloat(value.replace("R$", "").replace(".", "").replace(",", ".")); + } + const [productName, setProductName] = useState(''); + const [productDescription, setProductDescription] = useState(''); + const [productUnitId, setProductUnitId] = useState(''); + const [productSupplierId, setProductSupplierId] = useState(''); + const [productLocalId, setProductLocalId] = useState(''); + const [productSectorId, setProductSectorId] = useState(''); + const [isPerishable, setIsPerishable] = useState(false); + const [productCostValue, setProductCostValue] = useState(''); + const [productSellValue, setProductSellValue] = useState(''); + const [productStock, setProductStock] = useState(''); + const [productStockMin, setProductStockMin] = useState(''); + const [quantityMax, setQuantityMax] = useState(''); + const [productImage, setProductImage] = useState(null); + const [imagePreview, setImagePreview] = useState(null); + const [expirationDate, setExpirationDate] = useState(''); + const {id} = useParams(); + + const openProdEditModal = () => { + // setCurrentProduct(product); + setProductName(product.product_name); + setProductUnitId(product.unit_id); + setProductSupplierId(product.supplier_id); + setProductLocalId(product.supplier_id); + setProductSectorId(product.supplier_id); + setIsPerishable(product.is_perishable); + setProductCostValue(product.prod_cost_value); + setProductSellValue(product.prod_sell_value); + setProductStock(product.product_stock); + setProductStockMin(product.product_stock_min); + setQuantityMax(product.quantity_max); + + const imageUrl = product.product_img ? `http://localhost:3001${product.product_img}` : null; + setProductImage(imageUrl); + setImagePreview(imageUrl); + + if (product.description === null) { + setProductDescription(''); + } + + setIsProdEditModalOpen(true); + }; + + const closeProdEditModal = () => { + setIsProdEditModalOpen(false); + setCurrentProduct(null); + }; + + const handleProdUpdate = async (e) => { + e.preventDefault(); + + const updatedProductData = new FormData(); + updatedProductData.append('product_name', productName); + updatedProductData.append('description', productDescription); + updatedProductData.append('category_id', id); + updatedProductData.append('supplier_id', productSupplierId); + updatedProductData.append('is_perishable', isPerishable); + updatedProductData.append('unit_id', productUnitId); + updatedProductData.append("prod_cost_value", productCostValue); + updatedProductData.append("prod_sell_value", productSellValue); + updatedProductData.append('local_id', productLocalId); + updatedProductData.append('sector_id', productSectorId); + updatedProductData.append('product_stock', productStock); + updatedProductData.append('product_stock_min', productStockMin); + updatedProductData.append('quantity_max', quantityMax); + + if (productImage instanceof File) { + updatedProductData.append('product_img', productImage); + } + + try { + await api + .put(`/products/${product.product_id}`, updatedProductData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }) + .then((response) => console.log(response)); + flashInfo(); + closeProdEditModal(); + window.location.reload() + } catch (err) { + console.log(err); + flashError(); + } + }; + + const formatCurrency = (value) => { + const formattedValue = parseFloat(value.replace(/[^\d]/g, '') / 100).toLocaleString('pt-BR', { + style: 'currency', + currency: 'BRL' + }); + return formattedValue; + }; + + useEffect(() => { + if (productImage instanceof File) { + const previewUrl = URL.createObjectURL(productImage) + setImagePreview(previewUrl) + return () => URL.revokeObjectURL(previewUrl) + } else if (typeof productImage === 'string') { + setImagePreview(productImage) + } else { + setImagePreview(null) + } + }, [productImage]) + return ( -
+
- {'image + {`Imagem

{product.product_name}

+

{abbreviateNumber(product.product_stock) +" Und."}

{abbreviateNumber(product.prod_cost_value ,true)}

-
- +
+
+

Ver

+

Editar

+
+ + {/* Modal para editar produto */} + {isProdEditModalOpen && ( + +
+
+
document.getElementById('product-image-input').click()} + > + { + const file = e.target.files[0] + if (file) { + setProductImage(file) + setImagePreview(URL.createObjectURL(file)) + } + }} + name="product-image" + /> + {imagePreview ? ( + preview da imagem + ) : ( + + )} +
+
+ +
+
+ + setProductName(e.target.value)} + /> +
+ +
+ + +
+ +
+ + +
+ +
+
+ + setProductCostValue(formatCurrency(e.target.value))} + /> +
+ +
+ + setProductSellValue(formatCurrency(e.target.value))} + /> +
+
+ +
+ +
+ + {isPerishable && ( +
+ + setExpirationDate(e.target.value)} + /> +
+ )} +
+ +
+
+ + +
+ +
+ + +
+ +
+ +
+ setProductStockMin(e.target.value.replace(/\D/g, ''))} + /> + setProductStock(e.target.value.replace(/\D/g, ''))} + /> + setQuantityMax(e.target.value.replace(/\D/g, ''))} + /> +
+
+ + +
+
+
+
+
+ )} + + {/* Componente flash message, verifica se o estado flash é true e então renderiza a flash message */} + {flash && ( + setFlash(null)} + /> + )}
); } diff --git a/src/components/ProductModal/ProductModal.css b/src/components/ProductModal/ProductModal.css new file mode 100644 index 0000000..287d286 --- /dev/null +++ b/src/components/ProductModal/ProductModal.css @@ -0,0 +1,38 @@ +@media screen and (max-width: 1822px) { + .modal-box .prod-modal { + max-width: 75%; + } +} + +@media screen and (max-width: 1520px) { + .modal-box .prod-modal { + max-width: 95%; + } +} + +@media screen and (max-width: 1222px) { + .modal-main-container { + flex-direction: column; + } + + .modal-main-container > div { + width: 100%; + + } + + .modal-main-container > div:first-child > div { + margin: 0 auto; + } +} + +@media screen and (max-width: 512px) { + .modal-action { + justify-content: center; + } +} + +@media screen and (max-width: 470px) { + .preco-container { + flex-direction: column; + } +} \ No newline at end of file diff --git a/src/components/ProductModal/ProductModal.js b/src/components/ProductModal/ProductModal.js new file mode 100644 index 0000000..b11a1bb --- /dev/null +++ b/src/components/ProductModal/ProductModal.js @@ -0,0 +1,24 @@ +import React from 'react' +import './ProductModal.css' + +function ProductModal(props) { + return ( +
+
+

{props.title}

+ +
+ {props.children} + +
+ + +
+
+
+
+ + ) +} + +export default ProductModal \ No newline at end of file diff --git a/src/components/ProductTable/ProductTable2.js b/src/components/ProductTable/ProductTable2.js index 2944ab0..6b3ab4f 100644 --- a/src/components/ProductTable/ProductTable2.js +++ b/src/components/ProductTable/ProductTable2.js @@ -1,12 +1,13 @@ import { useState, useEffect } from 'react'; import ProductCell from '../ProductCell/ProductCell'; -import SearchBar from '../SearchBar/SearchBar'; import { useParams } from 'react-router-dom'; import Modalsbtn from '../Modal/Modalsbtn'; import Loading from '../Loading/Loading'; import api from '../../services/api'; import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/solid'; // Icones da Filtragem import ModalProducts from '../ModalProducts/ModalProducts'; +import ProductModal from '../ProductModal/ProductModal'; +import SearchBar from '../SearchBarAlt/SearchBarAlt'; const ProductTable = () => { const [modal, setIsModalOpen] = useState(false); @@ -23,6 +24,7 @@ const ProductTable = () => { const [currentPage, setCurrentPage] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(20); // Default to 20 for desktop + const { id } = useParams(); console.log(productInfo); @@ -145,15 +147,214 @@ const ProductTable = () => { return pages; }; + /** + * Retorna todas as unidades + */ + const [units, setUnits] = useState([]) + + const fetchUnits = async () => { + try { + await api + .get('/unit') + .then(response => setUnits(response.data)) + } catch(err) { + console.log(err) + } + } + + /** + * Retorna todos os fornecedores + */ + + const [suppliers, setSuppliers] = useState([]) + + const fetchSuppliers = async () => { + try { + await api + .get('/supplier') + .then(response => setSuppliers(response.data)) + } catch(err) { + console.log(err) + } + } + + /** + * Retorna todos os setores + */ + + const [sectors, setSector] = useState([]) + + const fetchSector = async () => { + try { + await api + .get('/sector') + .then(response => setSector(response.data)) + } catch(err) { + console.log(err) + } + } + + const [local, setLocals] = useState([]) + + const fetchLocals = async () => { + try { + await api + .get('/local') + .then(response => setLocals(response.data)) + } catch(err) { + console.log(err) + } + } + + /** + * Hook de useEffect para ativar as funções quando o componente é renderizado + */ + useEffect(() => { + const fetchData = async () => { + // setLoading(true) + await fetchUnits() + await fetchSuppliers() + await fetchProducts() + await fetchSector() + await fetchLocals() + } + fetchData() + }, []) + useEffect(() => { fetchProducts(); }, [id]); console.log('products', productInfo); + /** + * Abre e fecha o modal de produtos + */ + const [registerModal, setRegisterModal] = useState(false) + const openRegisterModal = () => setRegisterModal(true) + const closeRegisterModal = () => { + setProductName('') + setProductDescription('') + setProductUnitId('') + setProductSupplierId('') + setIsPerishable(false) + setProductSellValue('') + setProductCostValue('') + setProductSectorId('') + setProductLocalId('') + setProductBrand('') + setProductModel('') + setProductImage(null) + setProductStock('') + setProductStockMin('') + setQuantityMax('') + setRegisterModal(false) + } + + /** + * Registra o produto + */ + const [productDescription, setProductDescription] = useState(null) + const [productUnitId, setProductUnitId] = useState('') + const [productSupplierId, setProductSupplierId] = useState('') + const [isPerishable, setIsPerishable] = useState(false) + const [productBrand, setProductBrand] = useState('') + const [productModel, setProductModel] = useState('') + const [productCostValue, setProductCostValue] = useState('') + const [productSellValue, setProductSellValue] = useState('') + const [productLocalId, setProductLocalId] = useState('') + const [productSectorId, setProductSectorId] = useState('') + const [expirationDate, setExpirationDate] = useState('') + const [productImage, setProductImage] = useState(null) + const [productStock, setProductStock] = useState(null) + const [productStockMin, setProductStockMin] = useState(null) + const [quantityMax, setQuantityMax] = useState(null) + + const handleProductRegistration = async(e) => { + e.preventDefault() + + const formData = new FormData(); + formData.append('product_name', productname); + formData.append('description', productDescription); + formData.append('category_id', id); + formData.append('supplier_id', productSupplierId); + formData.append('is_perishable', isPerishable); + formData.append('unit_id', productUnitId); + formData.append('prod_model', productModel); + formData.append('prod_brand', productBrand); + formData.append("prod_cost_value", parseCurrencyToFloat(productCostValue)); + formData.append("prod_sell_value", parseCurrencyToFloat(productSellValue)); + formData.append('local_id', productLocalId); + formData.append('sector_id', productSectorId); + formData.append('product_stock', parseInt(productStock)); + formData.append('product_stock_min', parseInt(productStockMin)); + formData.append('quantity_max', parseInt(quantityMax)); + if (productImage) { + formData.append('product_img', productImage); + } + + try { + await api.post("/products", formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + .then(response => {setProducts((prevProducts) => [response.data, ...prevProducts])}) + + + setProductName('') + setProductDescription('') + setProductUnitId('') + setProductSupplierId('') + setIsPerishable(false) + setProductSellValue('') + setProductCostValue('') + setProductSectorId('') + setProductLocalId('') + setProductBrand('') + setProductModel('') + setProductImage(null) + setProductStock('') + setProductStockMin('') + setQuantityMax('') + closeModal() + flashSuccess() + } catch (err) { + console.log(err) + flashError() + } + } + + const formatCurrency = (value) => { + const formattedValue = parseFloat(value.replace(/[^\d]/g, '') / 100).toLocaleString('pt-BR', { + style: 'currency', + currency: 'BRL' + }); + return formattedValue; + }; + + const parseCurrencyToFloat = (value) => { + return parseFloat(value.replace("R$", "").replace(".", "").replace(",", ".")); + } + + useEffect(() => { + if (productImage instanceof File) { + const previewUrl = URL.createObjectURL(productImage) + setImagePreview(previewUrl) + return () => URL.revokeObjectURL(previewUrl) + } else if (typeof productImage === 'string') { + setImagePreview(productImage) + } else { + setImagePreview(null) + } + }, [productImage]) + return (
- +
+
Adicionar produto
+ +
{currentItems.map((product, index) => ( @@ -203,6 +404,227 @@ const ProductTable = () => { {productInfo ? : } )} + + {/* Modal de produto */} + {registerModal && ( + +
+
+
document.getElementById('product-image-input').click()} + > + { + setProductImage(e.target.files[0]); + }} + name="product-image" + /> + + + {imagePreview && ( +
+ preview da imagem +
+ )} +
+
+ +
+
+ + setProductName(e.target.value)} + /> +
+ +
+ + +
+ +
+ + +
+ +
+
+ + setProductCostValue(formatCurrency(e.target.value))} + /> +
+ +
+ + setProductSellValue(formatCurrency(e.target.value))} + /> +
+
+ +
+ +
+ + {isPerishable && ( +
+ + setExpirationDate(e.target.value)} + /> +
+ )} +
+ +
+
+ + +
+ +
+ + +
+ +
+ +
+ setProductStockMin(e.target.value.replace(/\D/g, ''))} + /> + setProductStock(e.target.value.replace(/\D/g, ''))} + /> + setQuantityMax(e.target.value.replace(/\D/g, ''))} + /> +
+ +
+ + +
+
+
+
+
+ )}
); }; diff --git a/src/components/ProductTable/ProductTableMvSt.js b/src/components/ProductTable/ProductTableMvSt.js index 94cfb00..68d2506 100644 --- a/src/components/ProductTable/ProductTableMvSt.js +++ b/src/components/ProductTable/ProductTableMvSt.js @@ -55,6 +55,10 @@ function ProductTableMvSt() { return pages; }; +<<<<<<< HEAD + +======= +>>>>>>> 845b428272a5465f464facb6ff0aa4423bd10ac8 const downloadPDF = async () => { try { const response = await Axios.get('http://localhost:3001/stock-movements/pdf', { @@ -214,7 +218,7 @@ function ProductTableMvSt() { {movement.batch ? movement.batch.batch_id : 'N/A'} {movement.movement_type} {movement.user ? movement.user.username : 'N/A'} - {new Date(movement.movement_date).toLocaleString()} + {movement.movement_date} {movement.category ? movement.category.category_name : 'N/A'} ))} @@ -222,41 +226,37 @@ function ProductTableMvSt() {
- - {/* Paginação */} -
+
- {paginationRange().map((page, index) => - page === '...' ? ( - ... - ) : ( - - ) - )} + {paginationRange().map((page, index) => ( + + ))}
- {isModalOpen && selectedMovement && (
@@ -285,4 +285,4 @@ function ProductTableMvSt() { ); } -export default ProductTableMvSt; +export default ProductTableMvSt; \ No newline at end of file diff --git a/src/components/Sidebar/Sidebari.js b/src/components/Sidebar/Sidebari.js index 1df306a..fe32ed5 100644 --- a/src/components/Sidebar/Sidebari.js +++ b/src/components/Sidebar/Sidebari.js @@ -111,7 +111,7 @@ function Sidebari({ content }) { } + icon={} component={} > Fornecedores @@ -127,7 +127,7 @@ function Sidebari({ content }) { {(role === 'admin' || role === 'gerente') && ( } + icon={} label="Gerenciar" className="poppins-semibold" @@ -137,7 +137,7 @@ function Sidebari({ content }) { }} > } + icon={} className="poppins-semibold" component={} onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#3E1900'} @@ -176,7 +176,7 @@ function Sidebari({ content }) { {collapsed ? 'Config' : 'Configurações'} */} } + icon={} className="poppins-semibold" component={} onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#3E1900'} @@ -196,7 +196,7 @@ function Sidebari({ content }) { {collapsed ? 'Fornecedores' : 'Fornecedores'} } + icon={} className="poppins-semibold" component={} onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#3E1900'} diff --git a/src/components/UserProfileIcon/UserProfileIcon.js b/src/components/UserProfileIcon/UserProfileIcon.js index 2926a91..40e5a64 100644 --- a/src/components/UserProfileIcon/UserProfileIcon.js +++ b/src/components/UserProfileIcon/UserProfileIcon.js @@ -45,6 +45,7 @@ function UserProfileIcon() { setUser(null); navigate('/login'); }; + if (!user) { return null; @@ -144,6 +145,7 @@ function UserProfileIcon() {
{user.user_img ? ( + - -
-
- - -
+
+ +
@@ -83,7 +81,7 @@ function Analytics() {
-
+
); } diff --git a/src/pages/BuyAndSell/BuyAndSell.js b/src/pages/BuyAndSell/BuyAndSell.js index 55200e4..d46ca4c 100644 --- a/src/pages/BuyAndSell/BuyAndSell.js +++ b/src/pages/BuyAndSell/BuyAndSell.js @@ -37,11 +37,8 @@ function BuyAndSell() {
- {/* Barra de pesquisa (componente que você pode personalizar se necessário) */} {/* Passando os produtos como prop para o ProductTable */} - -
diff --git a/src/pages/UserProfile/UserProfile.js b/src/pages/UserProfile/UserProfile.js index b8fcfd6..6d795bb 100644 --- a/src/pages/UserProfile/UserProfile.js +++ b/src/pages/UserProfile/UserProfile.js @@ -1,11 +1,155 @@ -import React from 'react' -import MainPage from '../MainPage/MainPage' +import React, { useState, useContext } from "react"; +import MainPage from "../MainPage/MainPage"; +import { UserContext } from "../../context/userContext"; +import api from "../../services/api"; function UserProfile() { + const { user, setUser } = useContext(UserContext); + const [username, setUsername] = useState(user?.username || ""); + const [isEditing, setIsEditing] = useState(false); + const [loading, setLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(null); + const [image, setImage] = useState(null); // Para armazenar a imagem selecionada + + const handleEdit = async () => { + console.log("Iniciando edição de usuário..."); + console.log("Enviando dados:", { user_id: user.user_id, username }); + + setLoading(true); + setError(null); + setSuccess(false); + + try { + const response = await api.put(`/users/${user.user_id}`, { username }); + console.log("Resposta da API:", response.data); + setUser({ ...user, username: response.data.username }); + setSuccess(true); + setIsEditing(false); + } catch (err) { + console.error("Erro na requisição:", err.response || err.message); + setError("Erro ao atualizar o nome. Tente novamente."); + } finally { + setLoading(false); + } + }; + + const handleImageChange = (e) => { + const file = e.target.files[0]; + if (file) { + setImage(file); // Armazena o arquivo real + } + }; + + const handleImageUpload = async () => { + if (!image) return; + + setLoading(true); + setError(null); + setSuccess(false); + + try { + const formData = new FormData(); + formData.append("user_img", image); // Envia o arquivo real como 'file' + + // Ajuste a URL conforme a API do seu backend + const response = await api.put(`/users/${user.user_id}`, formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); + + console.log("Imagem atualizada com sucesso:", response.data); + setUser({ ...user, user_img: response.data.user_img }); // Atualiza o usuário com a nova imagem + setSuccess(true); + } catch (err) { + console.error("Erro ao carregar a imagem:", err); + setError("Erro ao atualizar a imagem. Tente novamente."); + } finally { + setLoading(false); + } + }; + return ( +
+
+ {/* Exibição de imagem do usuário ou imagem padrão */} + User + + {/* Botão para alterar imagem */} +
+ + + {image && ( + + )} +
+ +
+

{user?.role}

+ {isEditing ? ( + setUsername(e.target.value)} + className="border rounded p-2 w-full mb-2 bg-[#F4E1C1] text-[#6B3710] poppins-semibold" + /> + ) : ( +

{user?.username}

+ )} +
+ +
+ {isEditing ? ( + <> + + + + ) : ( + + )} +
+ {error &&

{error}

} + {success &&

Atualizado com sucesso!

} +
+
- ) + ); } -export default UserProfile +export default UserProfile;