I have a React-Three-Fiber map project i'm working on, but running into a weird bug that I can't isolate.
On desktops the little map works perfectly, but once on Android, a transparent roughly 50(?)px size box in the middle of the viewport shows up and blocks and additional renderring in it until I pan the map past it.
Here's a video of what its doing:
https://youtu.be/4L1I9cZX1OM
Heres the code i'm using:
function App({moduleData}) {
const [floor, setFloor] = useState(1);
const [currentFloor, setCurrentFloor] = useState(floor);
const [riverwalkMap, setRiverwalkMap] = useState(moduleData.floor1.map_image.src);
const [currentPinSet, setCurrentPinSet] = useState('floor1');
const [pinInfo, setPinInfo] = useState()
const [zoomLevel, setZoomLevel] = useState(15);
const [pinHtml, setPinHtml] = useState("");
const [showMap, setShowMap] = useState(true);
const [pinHeader, setPinHeader] = useState("Unit: ");
const [open, setOpen] = useState(false);
const closeModal = () => setOpen(false);
function setPinColor(pinColor){
switch (pinColor){
case "green":
return 'pin_green.png'
case "red":
return 'pin_red.png'
case "yellow":
return 'pin_yellow.png'
default:
return 'pin_green.png'
}
}
function Scene({mapImage}){
const riverwalkMap = useLoader(TextureLoader, mapImage);
return(
<>
<mesh>
<planeGeometry args={[70,50]}/>
<meshBasicMaterial map={riverwalkMap} toneMapped={false}/>
</mesh>
</>
)
}
function Pin({props,pinInfo}){
const [active, setActive] = useState(0);
const [showPopup, setShowPopup] = useState(false);
const [hovered, setHovered] = useState(false);
useEffect(()=>{
document.body.style.cursor = hovered ? 'pointer' : 'auto'
},[hovered])
const { spring } = useSpring({
spring: active,
onChange: () => {
invalidate()
},
config: {mass:5, tension: 400, friction: 50, precision: 0.0001}
})
function returnPinClass(pin){
console.log('pin is: ' + pin);
switch (pin){
case 'available':
return '<span class="greenText">Available</span>';
default:
return '<span class="redText">Sold</span>';
}
}
function returnPinImage(pin){
console.log('pin image is: ' + pin);
return `<img src=${pin.src} alt=${pin.alt}/>`;
}
function setHtml(){
setPinHeader(`<h2>Unit: ${pinInfo.popup_title}</h2>`);
setPinHtml(`
<div class="popupContentBlock">
<div class="contentBlocks">
<div class="contentBlockLeft">
<div class="pdfViewer">
<iframe src="${pinInfo.pdf_file}"></iframe>
</div>
<div class="fractionalDiv">
Download PDF
</div>
</div>
</div>
</div>
`);
}
const scale = spring.to([0,1], [.6,1.25]);
const pinTexture = useLoader(TextureLoader, setPinColor(pinInfo.pin_color));
return(
<>
<a.mesh {...props}
scale-x={scale}
scale-y={scale}
scale-z={scale}
onPointerOver={(e)=> {
setActive(Number(!active));
}}
onPointerOut={(e)=>{
setActive(Number(!active));
}}
onClick={e => {
setHtml();
setOpen(o => !o);
// setShowMap(false);
}}
onPointerMissed={() => {setShowPopup(false)}}
position={[pinInfo.pin_position.x_pos,pinInfo.pin_position.y_pos,0]}
>
<planeGeometry args={[5,5]}/>
<meshBasicMaterial map={pinTexture} toneMapped={false} transparent={true}/>
</a.mesh>
</>
)
}
function setFloorButton(floor) {
setFloor(floor)
floorHeading(floor)
changePins(floor)
setCurrentFloor(floor)
}
function floorHeading(sentFloor) {
switch (sentFloor) {
case 1:
changeMap(moduleData.floor1)
return ReactHtmlParser(moduleData.floor1.heading);
case 2:
changeMap(moduleData.floor2)
return ReactHtmlParser(moduleData.floor2.heading);
case 3:
changeMap(moduleData.floor3)
return ReactHtmlParser(moduleData.floor3.heading);
case 4:
changeMap(moduleData.floor4)
return ReactHtmlParser(moduleData.floor4.heading);
default:
return 'No Floor Selected';
}
}
function changeMap(floorData) {
setRiverwalkMap(floorData.map_image.src);
}
function changePins(sentFloor){
setCurrentPinSet('floor'+sentFloor);
}
function closePop(){
setOpen(false);
}
function drawPins(currentSet){
switch (currentSet){
case 'floor1':
return moduleData.floor1.pins;
case 'floor2':
return moduleData.floor2.pins;
case 'floor3':
return moduleData.floor3.pins;
case 'floor4':
return moduleData.floor4.pins;
}
}
// THREE JS STUFF
// Drop Pins Programmatically
console.log(moduleData);
return (
<div className="cms-react-boilerplate__container">
<div className={"mapInfo"}>
<h1>Floor {currentFloor}</h1>
<p>Floors:</p>
<div className={"buttonSelector"}>
<button onClick={(e) => {
setFloorButton(1);
setPinHtml('');
}}>1</button>
<button onClick={(e) => {
setFloorButton(2);
setPinHtml('');
}}>2</button>
<button onClick={(e) => {
setFloorButton(3);
setPinHtml('');
}}>3</button>
<button onClick={(e) => {
setFloorButton(4);
setPinHtml('');
}}>4</button>
</div>
</div>
<div className={"mapGrid"}>
<div className={"mapDiv"} style={{ border: "2px solid black" }}>
<Canvas linear flat frameloop="demand" orthographic
camera={{position: [0, 0, 20], zoom: zoomLevel, up: [0, 0, 1], far: 10000}}
>
{showMap ? <Suspense fallback={null}>
{
drawPins(currentPinSet).map(e =>
<Pin pinInfo={e}/>
)}
<Scene mapImage={riverwalkMap}/>
</Suspense> : null}
<MapControls enableRotate={false}/>
</Canvas>
</div>
<div className={'infoLeft'} >
{!showMap ?
<div className={"infoGridBlock"}>
{ReactHtmlParser(pinHeader)}
<div className="closeButton" onClick={() => {
setShowMap(true);
setPinHtml('');
}}>
<p>✖</p>
</div>
</div>
: null }
<Popup open={open} closeOnDocumentClick onClose={closeModal} lockScroll={true}>
<div className={"modalBlock"} role="dialog">
<div className={"popupContentDiv"}>
<div className={"popupHeaderLeft"}>{ReactHtmlParser(pinHeader)}</div>
<div className={"popupHeaderRight"}><a onClick={closePop} aria-label="Close Popup">×</a></div>
</div>
{ReactHtmlParser(pinHtml)}
</div>
</Popup>
</div>
</div>
</div>
);
}
export default App;
What i've tried: I tried messing with some CSS but the closest i've gotten is if I force the React-Three-Fiber Canvas tag to have a unset height and width on mobile everything will render but no clickable elements will work.
Thank you for any help!
Related
I have created a 'working' duration slider, but I'm having trouble inserting 'leading zeros' into the hours and minutes:
const [hours, setHours] = useState([parseFloat(defaultValue.split(':')[0])])
const [minutes, setMinutes] = useState([parseFloat(defaultValue.split(':')[1])])
The above code is working, but will output (9hours & 5mins) as 9:5 (needs to be 09:05)
The code below (commented out in the full code) successfully puts in the leading zero's, but the code errors on line 61 and 97 where it's trying to handle the value
var leadingZeroHour = ('0000'+[parseFloat(defaultValue.split(':')[0])]).slice(-2)
const [hours, setHours] = useState(leadingZeroHour)
var leadingZeroMin = ('0000'+[parseFloat(defaultValue.split(':')[1])]).slice(-2)
const [minutes, setMinutes] = useState(leadingZeroMin)
The full code is below. If you can help me out and point me in the right direction, I'd be very grateful. Many thanks!
import React, { FunctionComponent, useState, useEffect } from 'react'
import { Range } from 'react-range'
type Props = {
className?: string,
defaultValue: string,
title?: string,
onUpdate: (value: string) => void;
[x: string]: any;
}
const defaultProps: Props = {
className: '',
defaultValue: '00:00',
title: '',
onUpdate: (value: any) => {},
}
const DurationInput: FunctionComponent<Props> = ({ className, defaultValue, title, onUpdate, ...rest }) => {
const [hours, setHours] = useState([parseFloat(defaultValue.split(':')[0])])
const [minutes, setMinutes] = useState([parseFloat(defaultValue.split(':')[1])])
// var leadingZeroHour = ('0000'+[parseFloat(defaultValue.split(':')[0])]).slice(-2)
// const [hours, setHours] = useState(leadingZeroHour)
// var leadingZeroMin = ('0000'+[parseFloat(defaultValue.split(':')[1])]).slice(-2)
// const [minutes, setMinutes] = useState(leadingZeroMin)
// console.log(hours)
useEffect(() => {
const duration = `${hours[0]}:${minutes[0]}`
onUpdate(duration)
}, [hours, minutes])
return (
<div className={`w-full ${className}`}>
{title ? <div className="text-base sm:text-xl mb-4 text-center">{title}</div> : <></>}
{/* <div className="grid grid-cols-3 gap-3 mb-8">
<div></div> */}
<div className="mx-auto w-40 sm:w-80 mb-8">
<div className="border border-orange rounded py-3 text-center text-4xl bg-white">
{hours}:{minutes}
</div>
<div></div>
</div>
<div className="mb-4 w-4/5 sm:w-3/5 mx-auto">
<div className="font-bold text-center mb-6">Hours</div>
<Range
step={1}
min={0}
max={23}
values={hours}
onChange={(values) => setHours(values)}
renderTrack={({ props, children }) => (
<div
{...props}
className="bg-orange rounded-full"
style={{
...props.style,
height: '6px',
width: '100%',
}}
>
{children}
</div>
)}
renderThumb={({ props }) => (
<div
{...props}
className="bg-white rounded-full border-4 border-orange"
style={{
...props.style,
height: '42px',
width: '42px',
}}
/>
)}
/>
</div>
<div className=" w-4/5 sm:w-3/5 mx-auto">
<div className="font-bold text-center mb-6">Minutes</div>
<Range
step={5}
min={0}
max={59}
values={minutes}
onChange={(values) => setMinutes(values)}
renderTrack={({ props, children }) => (
<div
{...props}
className="bg-orange rounded-full"
style={{
...props.style,
height: '6px',
width: '100%',
}}
>
{children}
</div>
)}
renderThumb={({ props }) => (
<div
{...props}
className="bg-white rounded-full border-4 border-orange"
style={{
...props.style,
height: '42px',
width: '42px',
}}
/>
)}
/>
</div>
</div>
)
}
DurationInput.defaultProps = defaultProps
export default DurationInput
I want to plus or minus the quantity of an item which is added in the cart. The issue is when I add another item to the cart and then when I plus or minus the quantity then the other item's quantity also changes. Also when quantity changes I want to add the total price of the quantity. I am using React Redux. Please help.
CART.JS
import React, { useState } from "react";
import "./cart.css";
import { useDispatch, useSelector } from "react-redux";
import {
clearCart,
minusQuantity,
plusQuantity,
removeFromCart,
} from "../../../redux/actions/CartActions";
const Cart = ({ id }) => {
const dispatch = useDispatch();
const product = useSelector((state) => state.addToCartReducer.products);
const qty = useSelector((state) => state.addToCartReducer.quantity);
// const minus = useSelector((state) => state.addToCartReducer.minus);
console.log(qty);
// console.log(minus);
const [quantity, setQuantity] = useState(1);
return (
<>
{product && (
<div
className={`dvCart ${id ? `col-lg-3` : `col-lg-2`} d-none d-lg-block`}
>
<div className="sticky-top" style={{ top: "90px" }}>
<div className="row">
<div className="col-sm-12 mb-1">
<h5 className="heading-5 d-inline-block mr-2">
Cart {product.length} items
</h5>
<span
className={`paragraph cp ${
product.length === 0 ? `d-none` : ``
}`}
onClick={() => dispatch(clearCart({}))}
>
clear all
</span>
</div>
{product && product.length === 0 ? (
<div className="dvCartEmpty col-12 d-none- mb-2">
<h5 className="heading-5 text-danger">Cart is Empty.</h5>
<p className="paragraph text-danger">
All Good No Bad! Go ahead, order some items from the menu.
</p>
{/* <!-- <img src="images/cart-empty.png" className="img-fluid" width="200" alt=""> --> */}
</div>
) : (
<div className="dvCartItems col-sm-12 mb-2">
<div className="row">
<div className="scrollbar mr-3">
{product.map((item) => {
const { id, heading, img, price, pack, size } = item;
return (
<div key={id} className="item col-sm-12 mb-2 pr-0">
<div className="bg-light pt-2 pb-2">
<div className="col-12">
<h5 className="heading-5">{heading}</h5>
<span className="paragraph mb-1 mr-2">
{size}
</span>
<span
className={`paragraph mb-1 ${
pack === `pack of 0` ? `d-none` : ``
}`}
>
{pack}
</span>
</div>
<div className="col-sm-12">
<div className="d-flex justify-content-between align-items-center">
<div className="addBtn d-flex justify-content-center align-items-center flex-1">
<div className="flex-1 text-center">
<i
className="fa fa-minus mr-1 cp p-1"
onClick={() =>
dispatch(
minusQuantity({ quantity: 1 })
)
}
></i>
</div>
<div className="flex-3 text-center">
<input
type="text"
value={qty}
onChange={(e) =>
setQuantity(e.target.value)
}
className="form-control text-center p-0"
/>
</div>
<div className="flex-1 text-center">
<i
className="fa fa-plus ml-1 cp p-1"
onClick={() =>
dispatch(
plusQuantity({ quantity: 1, id })
)
}
></i>
</div>
</div>
<div className="paragraph text-right">
<i className="fa fa-inr"></i>
{price}
</div>
</div>
</div>
<button
onClick={() =>
dispatch(
removeFromCart({ id, heading, price, size })
)
}
className="btn btn-remove"
>
<i className="fa fa-close"></i>
</button>
</div>
</div>
);
})}
</div>
</div>
</div>
)}
<div className="dvSubTotal col-sm-12 mb-2">
<div className="d-flex justify-content-between">
<div>
<h5 className="heading-5 text-success">Subtotal</h5>
</div>
<div>
<p className="heading-5 text-success">
<i className="fa fa-inr"></i>
{product
.map((item) => item.price)
.reduce((prev, curr) => prev + curr, 0)}
.00
</p>
</div>
</div>
<p className="paragraph">Extra charges may apply.</p>
</div>
<div className="dvProceed col-sm-12 mb-2">
<button
disabled={product.length !== 0 ? false : true}
className="btn btn-black w-100"
>
Proceed
</button>
</div>
</div>
</div>
</div>
)}
</>
);
};
export default Cart;
PRODUCTLIST.JS
import React, { useState } from "react";
import { Link } from "react-router-dom";
import "./productlist.css";
import ProductNotFound from "../../other/product-not-found/ProductNotFound";
import { useDispatch, useSelector } from "react-redux";
import { addToCart } from "../../../redux/actions/CartActions";
const ProductList = ({
id,
img,
pack,
price,
size,
heading,
description,
notfound,
}) => {
const dispatch = useDispatch();
// const [isDisabled, setIsDisabled] = useState(false);
const products = useSelector((state) => state.addToCartReducer.products);
// const isDisabled = useSelector((state) => state.addToCartReducer.isDisabled);
// console.log(isDisabled);
// console.log(products);
return (
<>
{notfound ? (
<ProductNotFound />
) : (
<div className="col-6 col-md-4 col-lg-6 col-xl-3 mb-4">
<div className="border border-light shadow-sm p-1 h-100">
<div className="image">
<p className={pack !== "pack of 0" ? "packs" : "d-none"}>
{pack}
</p>
<div className="bg-light text-center pt-2 pb-2 mb-1">
<Link className="d-inline-block" to={`/${id}`}>
<img src={img} className="img-fluid" alt={heading} />
</Link>
</div>
<h5 className="heading-5 text-center">{heading}</h5>
</div>
<div className="description d-flex justify-content-between mb-1">
<div className="paragraph">
<p>{size}</p>
</div>
<div className="paragraph mr-2">
<span>
<i className="fa fa-inr"></i>
<span>{price}</span>
</span>
</div>
</div>
<div className="addBtn text-center">
<button
onClick={() =>
dispatch(
addToCart({
id,
img,
pack,
price,
size,
heading,
description,
})
)
}
className="btn btn-white w-100"
disabled={products.find((item) => item.id === id) && true}
>
Add to Bag
</button>
</div>
</div>
</div>
)}
</>
);
};
export default ProductList;
CART ACTIONS.JS
import { actionTypes } from "../constants/action-types";
//ADD TO CART
export const addToCart = (item) => {
return {
type: actionTypes.ADD_TO_CART,
payload: item,
};
};
//PLUS QUANTITY
export const plusQuantity = (item) => {
return {
type: actionTypes.PLUS_QUANTITY,
payload: item,
};
};
//MINUS QUANTITY
export const minusQuantity = (item) => {
return {
type: actionTypes.MINUS_QUANTITY,
payload: item,
};
};
//REMOVE FROM CART
export const removeFromCart = (item) => {
return {
type: actionTypes.REMOVE_FROM_CART,
payload: item,
};
};
//CLEAR CART
export const clearCart = (item) => {
return {
type: actionTypes.CLEAR_CART,
payload: item,
};
};
CART REDUCER.JS
import { actionTypes } from "../constants/action-types";
const addToCartiState = {
products: [],
quantity: 1,
// minus: 0,
};
//CART REDUCER
export const addToCartReducer = (state = addToCartiState, action) => {
console.log(state);
console.log(action);
switch (action.type) {
case actionTypes.ADD_TO_CART:
return {
...state,
products: [...state.products, action.payload],
};
case actionTypes.PLUS_QUANTITY:
return {
...state,
//i am not sure if this logic is correct
quantity: state.quantity + action.payload.quantity,
};
case actionTypes.MINUS_QUANTITY:
return {
...state,
//i am not sure if this logic is correct
quantity:
state.quantity > 1 ? state.quantity - action.payload.quantity : 1,
};
case actionTypes.REMOVE_FROM_CART:
const filteredID = state.products.filter(
(item) => item.id !== action.payload.id
);
return {
...state,
products: filteredID,
};
case actionTypes.CLEAR_CART:
return {
...state,
products: [],
};
default:
return state;
}
};
Total cart quantity should be derived state and not stored in state. You should instead store an item quantity and compute a total quantity when rendering.
Add a quantity property when adding an item to the cart. If the item has already been added then simply update the quantity instead of adding a duplicate item.
Example item object:
{
id,
img,
pack,
price,
size,
heading,
description,
}
Cart reducer
const addToCartiState = {
products: [],
};
export const addToCartReducer = (state = addToCartiState, action) => {
switch (action.type) {
case actionTypes.ADD_TO_CART:
const isInCart = state.products.some(item => item.id === action.payload.id);
if (isInCart) {
// update existing item in cart
return {
...state,
products: state.products.map(
item => item.id === action.payload.id
? {
...item,
quantity: item.quantity + 1,
}
: item
),
};
}
// add new item to cart
return {
...state,
products: [
...state.products,
{
...action.payload,
quantity: 1
},
],
};
case actionTypes.PLUS_QUANTITY:
return {
...state,
products: state.products.map(
item => item.id === action.payload.id
? {
...item,
quantity: item.quantity + action.payload.quantity
}
:item
),
};
case actionTypes.MINUS_QUANTITY:
const item = state.products.find(item => item.id === action.payload.id);
if (item?.quantity === 1) {
// new quantity is 0, remove item from cart
return {
...state,
products: state.products.filter(item => item.id !=== action.payload.id),
};
}
// decrement quantity
return {
...state,
products: state.products.map(
item => item.id === action.payload.id
? {
...item,
quantity: item.quantity - action.payload.quantity
}
:item
),
};
case actionTypes.REMOVE_FROM_CART:
return {
...state,
products: state.products.filter(
(item) => item.id !== action.payload.id
),
};
case actionTypes.CLEAR_CART:
return {
...state,
products: [],
};
default:
return state;
}
};
Compute the derived cart total item quantity in the UI.
const Cart = ({ id }) => {
const dispatch = useDispatch();
const products = useSelector((state) => state.addToCartReducer.products);
const quantity = products.reduce((total, { quantity }) => total + quantity, 0);
console.log(quantity);
I have a problem capturing multiple images to my function in vue and pass to the controller. I am trying to modify my blade file which works well when using just the normal form. I am trying to modify to vue but I have a problem with image section. Please assist me on how to achieve this.
my form:
<label for="">Description</label>
<textarea name="description" class="form-control" v-model="description"> </textarea>
<label for="">Images</label>
<input type="file" #change="fieldChange" class="form-control input-sm" name="images[]"
multiple>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
The vue section
data(){
return {
id:'',
price:'',
title:'',
description:'',
location:'',
images:[],
}
},
methods:{
fieldChange(e){
let selectedFiles=e.target.files;
if(!selectedFiles.length){
return false;
}
for(let i=0;i<selectedFiles.length;i++){
this.images.push(selectedFiles[i]);// am able to console the images
}
},
saveImageData(){
var self=this;
axios.post('/senddata',{
title:this.title,
description:this.description,
location:this.location,
images:this.images.file.name,
price:this.price,
})
},
My Laravel function
public function store(Request $request)
{
$product=Products::create([
'title'=>$request['title'],
'description'=>$request['description'],
'price'=>$request['price'],
'location'=>$request['location']
]);
$images= $request->file('images');
foreach ($images as $image){
$move=$image->move(public_path().'/images2/',$image->getClientOriginalName());
if($move){
$imagedata=Images::create([
'title'=>$image->getClientOriginalName(),
'filename'=>$image->getClientOriginalName()
]);
$product->images()->attach([$imagedata->id]);
}
Here is the working code for vuejs part - https://picupload.netlify.app/
https://github.com/manojkmishra/dw_take5/blob/master/src/components/ImageUploader.vue
Vue part
<template>
<div class="uploader"
#dragenter="OnDragEnter"
#dragleave="OnDragLeave"
#dragover.prevent
#drop="onDrop"
:class="{ dragging: isDragging }">
<div class="upload-control" v-show="images.length">
<label for="file">Select files</label>
<button #click="upload">Upload</button>
</div>
<div v-show="!images.length">
<i class="fa fa-cloud-upload"></i>
<p>Drag your images here</p><div>OR</div>
<div class="file-input">
<label for="file">Select files</label>
<input type="file" id="file" #change="onInputChange" multiple>
</div>
</div>
<div class="images-preview" v-show="images.length">
<div class="img-wrapper" v-for="(image, index) in images" :key="index">
<img :src="image" :alt="`Image Uplaoder ${index}`">
<div class="details">
<span class="name" v-text="files[index].name"></span>
<span class="size" v-text="getFileSize(files[index].size)"> </span>
</div>
</div>
</div>
<div v-show="images.length" class="progress">
<div
class="progress-bar progress-bar-info progress-bar-striped"
role="progressbar" :aria-valuenow="progress"
aria-valuemin="0" aria-valuemax="100"
:style="{ width: progress + '%' }"
>
{{ progress}}%
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default
{ data: () => ({ isDragging: false, dragCount: 0, files: [],images: [] ,progress:0}),
methods: {
OnDragEnter(e) { e.preventDefault();
this.dragCount++;
this.isDragging = true;
return false;
},
OnDragLeave(e) { e.preventDefault();
this.dragCount--;
if (this.dragCount <= 0) this.isDragging = false;
},
onInputChange(e) { const files = e.target.files;
Array.from(files).forEach(file => this.addImage(file));
},
onDrop(e) {console.log('ondrop-evnt e=',e)
e.preventDefault();
e.stopPropagation();
this.isDragging = false;
const files = e.dataTransfer.files;
Array.from(files).forEach(file => this.addImage(file));
},
addImage(file) {console.log('addimage file=',file)
if (!file.type.match('image.*')) { this.$toastr.e(`${file.name} is not an image`);
return;
}
this.files.push(file);
const img = new Image(),
reader = new FileReader();
reader.onload = (e) => this.images.push(e.target.result);
reader.readAsDataURL(file);
console.log('addimage this.images=',this.images)
},
getFileSize(size) { const fSExt = ['Bytes', 'KB', 'MB', 'GB'];
let i = 0;
while(size > 900) { size /= 1024; i++; }
return `${(Math.round(size * 100) / 100)} ${fSExt[i]}`;
},
upload() { //this.progress = '0';
const formData = new FormData();
this.files.forEach(file =>
{ formData.append('images[]', file, file.name); });
console.log('upload triggered FormData=',formData)
// resp=axios.post('http://127.0.0.1:8000/sendemail1',this.formData);
// axios.post('http://127.0.0.1:8000/api/imagesupload', formData,
axios.post('https://uat.oms.dowell.com.au/api/imagesupload', formData,
{onUploadProgress:uploadEvent=>{ this.progress=Math.round(uploadEvent.loaded/uploadEvent.total*100);
console.log('upld prges:'+ Math.round(uploadEvent.loaded/uploadEvent.total*100)+'%')
}
})
//axios.post('https://uat.oms.dowell.com.au/api/imagesupload', formData)
.then(response => {
this.$toastr.s('All images uplaoded successfully');
this.images = [];
this.files = [];
this.progress = 0;
})
.catch(() => {
this.$toastr.e('Could not upload the files!');
this.images = [];
this.files = [];
this.progress = 0;
});
}
}
}
</script>
Another version with vuetify
https://github.com/manojkmishra/take5-front-admin/blob/master/src/components/img/imgup.vue
Here is laravel part
public function imagesupload(Request $request){
if (count($request->images)) {
foreach ($request->images as $image) {
$image->store('images');
}
}
return response()->json(["message" => "Done"]);
}
Another way in laravel is here
https://github.com/manojkmishra/take5-api/blob/master/app/Http/Controllers/PicController.php
I want to display the Child component on click on Button, But here I am getting the Data when the page loads,I need to write a condition like when Button Clicked , then only the Child component show display otherwise a default text should display there.
const DetailsCard = () => {
const [employee, setemployee] = useState([])
const [data, setData] = useState()
useEffect(() => {
fetch("http://localhost:3000/users").then(res => res.json()).then((result) => {
setemployee(result);
}, [])
})
const handleChange = () => {
setData(true);
}
return (
<div>
<h1>LordShiva</h1>
<div className="container">
<div className="row">
<div className="col">
<div className="card">
<div className="card-header bg-primary text-white">
<p className="h4">Birthday APP</p>
<button className="btn btn-red true1 " onClick={handleChange} >HappyBirthday</button>
</div>
<div className="card-body">
<TableCard data={employee} />
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default DetailsCard;
const DetailsCard = () => {
const [employee, setemployee] = useState([]);
const [showChild, toggleShowChild] = useState(false);
useEffect(() => {
fetch("http://localhost:3000/users")
.then((res) => res.json())
.then((result) => {
setemployee(result);
}, []);
});
const handleChange = () => {
toggleShowChild(!showChild);
};
return (
<div>
<h1>LordShiva</h1>
<div className="container">
<div className="row">
<div className="col">
<div className="card">
<div className="card-header bg-primary text-white">
<p className="h4">Birthday APP</p>
<button className="btn btn-red true1 " onClick={handleChange}>
HappyBirthday
</button>
</div>
{/* Only show child when `showChild` is true. */}
{showChild && (
<div className="card-body">
<TableCard data={employee} />
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
};
export default DetailsCard;
Codesandbox
import React, { useState, useEffect } from "react";
const FetchAPI = () => {
const [data, setData] = useState([]);
const newData = data.slice(0, 12);
const [showData, setShowData] = useState(false);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((response) => response.json())
// .then((json) => console.log(json));
.then((json) => setData(json));
}, []);
const onClickhandler = () => {
setShowData(!showData);
};
return (
<>
<h1>Search</h1>
<ul>
{newData.map((item) => {
return showData ? (
<li style={{ listStyle: "none", marginTop: "10px" }} key={item.id}>
{item.title}
</li>
) : (
""
);
})}
</ul>
<button onClick = {onClickhandler}>
Fetch
</button>
</>
);
};
export default FetchAPI;
I m developing an e-commerce application with react hooks in search component result is shown beneath the component I want to render on search Result component how to redirect search result on the search Result component
import React, { useState, useEffect } from "react";
import { Link, Redirect } from "react-router-dom";
import { getCategories, list } from "./apiCore";
import SearchResult from "./SearchResult";
const Search = () => {
const [data, setData] = useState({
categories: [],
category: "",
search: "",
results: [],
searched: false,
});
const { categories, category, search, results, searched } = data;
const loadCategories = () => {
getCategories().then(data => {
if (data.error) {
console.log(data.error);
} else {
setData({ ...data, categories: data });
}
});
};
useEffect(() => {
loadCategories();
}, []);
const searchData = () => {
// console.log(search, category);
if (search) {
list({ search: search || undefined, category: category }).then(
response => {
if (response.error) {
console.log(response.error);
} else {
setData({ ...data, results: response, searched: true });
}
}
);
}
};
const searchSubmit = e => {
e.preventDefault();
searchData();
};
const handleChange = name => event => {
setData({ ...data, [name]: event.target.value, searched: false });
};
const searchMessage = (searched, results) => {
if (searched && results.length > 0) {
return `Found ${results.length} products`;
}
if (searched && results.length < 1) {
return `No products found`;
}
};
const searchedProducts = (results = []) => {
return (
<div>
<h2 className="text-muted mb-4">
{searchMessage(searched, results)}
</h2>
<div className="row">
{results.map((product, i) => (
<CarouselCard key={i} product={product} />
))}
</div>
</div>
);
};
return (
<div className="site-navbar-top">
<div className="container">
<div className="row align-items-center">
<div className="col-6 col-md-4 order-2 order-md-1 site-search-icon text-left">
<form className="site-block-top-search" onSubmit={searchSubmit}>
<span className="icon icon-search2"></span>
<input type="text" className="form-control border-0" placeholder="Search" onChange={handleChange("search")} />
</form>
</div>
<div className="col-12 mb-3 mb-md-0 col-md-4 order-1 order-md-2 text-center">
<div className="site-logo">
<Link to="/" className="js-logo-clone">Shoppers</Link>
</div>
</div>
<div className="col-6 col-md-4 order-3 order-md-3 text-right">
<div className="site-top-icons">
<ul>
<li><Link to="#"><span className="icon icon-person" /></Link></li>
<li><Link to="#"><span className="icon icon-heart-o" /></Link></li>
<li>
<Link to="cart.html" className="site-cart">
<span className="icon icon-shopping_cart" />
<span className="count">2</span>
</Link>
</li>
</ul>
</div>
</div>
</div>
</div>
{searchedProducts(results)}
</div>
)
}
export default Search;
The main part of the hook is pretty straightforward, but I'm having a difficult time finding a nice way to handle that redirect. The current working solution is to wrap the functional component with withRouter, then pass props.history