Laravel + Vue Looping a Specific ID once - laravel

Hey guys so I'm planning to have a list of my recent chats. The problem is that i just want to loop the same Id (ex. Chatroom_id), in my case its looping the same the Chatroom Id 5 times, cause im checking a db that reciever_id is mine and the result is 5, hence the 5 times it loops the same Chatroom ID. I just want it to loop once ever chatroom Id
Laravel View // where i insert my vue component
<!--- Message or online followers and followings -->
<div id="messagesidebar" class="app-sidebar-userdetails">
<h6 class="sm text-white"> <i> Recent Chat </i> </h6>
<div id="recentchat">
<recentchat-component :user_id="{{ Auth::user()->id }}"></recentchat-component>
</div>
</div>
<!-- /# Message or online followers and followings -->
</div>
Vue Template
<div class="chats" v-for="recentchat in recentchats" v-bind:key="recentchat.id">
{{ recentchat.chatroom_id}}
</div>
Laravel Controller
public function fetchrecentchat($user_id)
{
$recentchat = Chat::Where('receiver_id', $user_id)
->orderBy('created_at', 'DESC')
->get();
return ChatResource::collection($recentchat);
}
Chat Resource
public function toArray($request)
{
// return parent::toArray($request);
return [
'id' => $this->id,
'message' => $this->message,
'chatroom_id' => $this->chatroom_id,
'user_id' => $this->user_id,
'receiver_id' => $this->receiver_id,
'created_at' => $this->created_at->diffForHumans(),
'updated_at' => $this->updated_at,
];
}
Tell me if you need to review codes that i did not add above so much thanks guys!
Update
Vue script
<script>
export default {
props: [ 'user_id' ],
data() {
return {
recentchats: [],
recentchat: {
id: '',
chatroom_id: '',
user_id: '',
receiver_id: '',
created_at: '',
updated_at: '',
}
}
},
created() {
this.fetchchatrooms();
},
methods: {
fetchchatrooms(){
fetch('/api/fetchrecentchat/' +this.user_id)
.then(res => res.json())
.then(res => {
console.log(res);
this.recentchats = res.data
});
}
},
mounted() {
console.log('Recent Chat mounted.')
}
}

Related

How to prevent stripe from creating new user when receiving a payment?

I am starting with stripe and still in test mode.
I use Laravel 9 + cashier and vuejs
I also installed vue-stripe and created a view to test the checkout functionality.
Here is my vue
<template>
<div class="text-xl sass-editor-1 text-center">
<h1 class="text-2xl">Stripe Payment Gateway integration</h1>
<div class="container" v-if="payId">
<stripe-checkout
ref="checkoutRef"
:pk="publishableKey"
:sessionId="payId"
:customerEmail="customerEmail" />
<button class="border-2 rounded-lg bg-green-800 text-white p-3 mt-4" #click="submit">Pay Now!</button>
</div>
{{customerEmail}}
<div v-if="subscribeId" class="container">
<stripe-checkout
ref="subRef"
:pk="publishableKey"
:sessionId="subscribeId"
:customerEmail="customerEmail" />
<button class="border-2 rounded-lg bg-green-800 text-white p-3 mt-4" #click="submitSub">Subscribe Now!</button>
</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
import { StripeCheckout , Stripe} from '#vue-stripe/vue-stripe';
import axios from "../axios"
import store from "../store"
export default {
components: {
StripeCheckout,
},
data() {
return {
publishableKey: 'pk_test_51M6ZtzI....................XgAyUVjlwG6MFos0AaqaQYJOf2YC3a6oWlZqMjFtTZj00Tue51qVs',
payId: null,
subscribeId: null,
customerEmail: store.state.user.email
}
},
methods: {
getSession() {
axios.get('api/getSession')
.then(res => {
console.log(res);
this.payId = res.data.oneTime.id;
this.subscribeId = res.data.sub.id;
})
.catch(err => {
console.log(err);
})
},
submit() {
this.$refs.checkoutRef.redirectToCheckout();
},
submitSub() {
this.$refs.subRef.redirectToCheckout();
}
},
mounted() {
this.getSession();
}
}
</script>
and here is the StripeController to return the sessionId in the backend
<?php
namespace App\Http\Controllers;
use Stripe\StripeClient;
use Illuminate\Http\Request;
use Laravel\Cashier\Cashier;
class StripeController extends Controller
{
public function getSession()
{
$stripe = new StripeClient(env('STRIPE_SECRET'));
$user=auth()->user();
$stripeCustomer = $user->createOrGetStripeCustomer(
['name'=>$user->name,'email'=>$user->email]);
$checkout = $stripe->checkout->sessions->create(
[
'success_url' => 'https://yahoo.com',
'cancel_url' => 'https://google.com',
'line_items' =>
[
[
'price_data' =>
[
'currency' => 'eur',
'unit_amount' => 500,
'product_data' =>
[
'name' => 'Example Stripe Checkout'
],
],
'quantity' => 1,
],
],
'mode' => 'payment',
]
);
$sub = $stripe->checkout->sessions->create(
[
'success_url' => 'https://denentzat.fr',
'cancel_url' => 'https://google.com',
'line_items' =>
[
[
'price'=>'price_1M84UNIWDjpHNQK1FXOj1k01',
'quantity' => 1,
],
],
'mode' => 'subscription',
]
);
return ['oneTime'=>$checkout, 'sub'=>$sub];
}
public function webhook(Request $request){
\Log::info($request->data);
return response()->json(['status'=>'success']);
}
}
The payment is done in both cases (pay or subscribe).
Nevertheless, when I go in the customer tab of the dashboard, I can see that sometimes (I could not find for what reason) stripe create a guest user, or a normal user and
eventually, there may be several users with the same email. How to prevent this?
I was hoping that in passing the user email to the form (Stripe-checkout component) this will prefill the email field but it doesn't happen.
Thank you for help.
You can pre-create a Customer with their email, then passing in the Customer Id when creating the Checkout Session. (see Existing Customer on Stripe Doc).

Looking for a way to translate(i18n) laravels form validation rules inside a Vue form

So I have build an form in laravel with Vue with some validation rules and this works, when there's an error it will show me an message but I also have an locales switcher present which also works for the text in the form but not for the validation output, so there are always in English. I am using the i18n
plugin to translate the text.
Is there a way to make the validation rules i18n ready?
registerController.php
protected function validator(array $data)
{
$customMessages = [
'name' => 'some custom message can go here...',
];
$validator = Validator::make($data, [
'name' => ['required', 'min:2', 'string', 'max:100'],
'email' => ['required', 'email', 'string', 'max:255', 'unique:users'],
'password' => [
'required'
'min:10',
'regex:/[a-z]/', // must contain at least one lowercase letter
'regex:/[A-Z]/', // must contain at least one uppercase letter
'regex:/[0-9]/', // must contain at least one digit
'regex:/[#$!%*#?&]/', // must contain a special character
],
], $customMessages);
return $validator;
}
componentForm.vue
<template>
<form #submit.prevent="formSubmit">
<el-input type="text" name="name" v-model="fields.name"
label="Name" :error="errors.name"/>
<el-input type="email" name="email" v-model="fields.email"
label="E-mailaddress" :error="errors.email"/>
<el-input type="password" name="password" v-model="fields.password"
label="Password" :error="errors.password"/>
<button type="submit" class="btn btn--primary btn--xl btn--block">
{{ $t("auth.register") }}
</button>
</form>
</template>
<script>
import espressoLocale from '../../Components/Contextual/Locale';
import espressoCard from '../../Components/UI/Card';
import elInput from '../../Components/Forms/Input';
export default {
components: {
elInput,
},
data() {
return {
fields:{
name: "",
email: "",
password: "",
},
errors: {
name: null,
email: null,
password: null,
},
}
},
methods: {
resetFields () {
this.fields.name = "";
this.fields.email = "";
this.fields.password = "";
},
formSubmit (e) {
e.preventDefault();
this.errors = {};
axios.get('/sanctum/csrf-cookie').then(response => {
axios({
method: 'post',
url: '/api/register',
data: {
name: this.fields.firstname,
email: this.fields.email,
password: this.fields.password,
},
validateStatus: (status) => {
return true;
}
}).then(response => {
if (response.data.success) {
} else {
this.errors = response.data.errors || {};
}
}).catch(function (error) { });
});
}
},
}
</script>
You should write :error="$t(errors.name)" in your components as you write {{ $t("auth.register") }} to show translated text about register. I assume that you get i18n locale structured object in your errors response, something like this:
errors: {
name: 'errors.name',
...
}

data not stored in laravel back end from axios post of vue js front end

I have some data that i need to store in my database coming from localStorage. One is an input field where a user can change the quantity of an item, the other is a radio box where the user has to select an address to deliver to. The issue is that it just won't store the address_id in my database nor update the qty field of the input in my cart. Could someone take a look at it and explain why this doesn't work? I'd appreciate it so much thanks!
Note: The data object is reactive, I checked in my vue dev tools and it changes the data correclty so no issue there.
Vue add to cart button component:
<template>
<form #submit.prevent="addToCart">
<button>Add to cart</button>
</form>
</template>
<script>
export default {
props: ['productId', 'categoryId'],
data() {
return {
product: {},
cart: []
}
},
methods: {
fetchData() {
axios.get(`http://localhost:8000/api/product/${this.productId}/category/${this.categoryId}`)
.then(res => {
const { product } = res.data;
this.product.id = product.id
this.product.title = product.title;
this.product.fitSize = product.fit_size;
this.product.jeansSize = product.jeans_size;
this.product.price = product.price;
this.product.img = product.images[0].images;
this.product.quantity = 1;
})
.catch(err => console.log(err))
},
addToCart() {
if(localStorage.getItem('cart')) {
// Little note to myself:
// Grab data from local storage and turn it into a js array of objects
// Push new product to that array every time the addToCart method gets fired
// get that array with the additional items and store back in local storage as a JSON string
let cart = JSON.parse(localStorage.getItem('cart'));
cart.push(this.product)
return localStorage.setItem('cart', JSON.stringify(cart))
} else {
this.cart.push(this.product)
localStorage.setItem('cart', JSON.stringify(this.cart))
}
}
},
mounted() {
this.fetchData()
}
}
</script>
Vue checkout component:
<template>
<div>
<div v-for="product in products" v-bind:key="product.id">
<p>Img: {{product.img}}</p>
<p>Title: {{product.title}}</p>
<p>Price: {{product.price}}</p>
<input v-model="product.quantity" type="number" name="qty" id="qty">
<br>
</div>
<form method="POST" #submit.prevent="placeOrder">
<div v-for="address in user.addresses" v-bind:key="address.id">
<input type="radio" v-model="addressId" v-bind:value="address.id" name="address_id" id="address_id">{{address.street}}
</div>
<button>Place order</button>
</form>
</div>
</template>
<script>
export default {
props: ['user'],
data() {
return {
products: null,
addressId: null,
orders: [],
}
},
methods: {
fetchDataFromLocalStorage() {
this.products = JSON.parse(localStorage.getItem('cart'))
},
createOrders() {
this.products.forEach(product => {
this.orders.push({
qty: product.quantity,
user_id: this.user.id,
product_id: product.id,
address_id: this.addressId
})
})
},
placeOrder() {
const sendOrders = { orders: this.orders }
axios.post(`http://localhost:8000/api/user/${this.user.id}/checkout`, sendOrders)
.then(res => console.log(res.data))
.catch(err => console.log(err))
},
},
mounted() {
this.fetchDataFromLocalStorage();
this.createOrders();
}
}
</script>
Laravel store method:
public function store(Request $request, $id)
{
foreach ($request->orders as $order) {
Order::create([
'qty' => $order['qty'],
'product_id' => $order['product_id'],
'user_id' => $order['user_id'],
'address_id' => $order['address_id']
]);
}
return response()->json('Order created');
}
Order model:
class Order extends Model
{
protected $guarded = [];
public function product()
{
return $this->hasOne(Product::class);
}
public function user()
{
return $this->belongsTo(Order::class);
}
public function addresses()
{
return $this->hasOne(Addresses::class);
}
}
Laravel api route:
Route::post('/user/{id}/checkout', 'CheckoutController#store');
Tinker when I make a post request:
App\Order {#3072
id: "127",
qty: "1", // Default value just won't change whenever I try to update it!
delivered: "0",
product_id: "3", // This works
created_at: "2019-12-23 10:08:09",
updated_at: "2019-12-23 10:08:09",
user_id: "1", // This works
address_id: null, // This doesn't
},
],

Foreign key on post request Laravel & Vue

I am using a larvel backend with a vue frontend. They are connected by API. I have been trying to figure out how i can correctly submit a form for a model that has a foreign_key relationship with a parent model.
Here is the relationships
A User has many Tasks
A Task belongs to User
A Client has many Engagements
A Engagement belongs to Client
Engagements and Tasks have many to many
User and Client have no direct relationship
So I know that if i wanted to submit a post request for data that had a relationship with user It would be simple to assign the foreign_key like below
*Example
public function store(Request $request)
{
$data = $request->validate([
'title' => 'required|string',
'completed' => 'required|boolean',
]);
$todo = Todo::create([
'user_id' => auth()->user()->id,
'title' => $request->title,
'completed' => $request->completed,
]);
return response($todo, 201);
}
But when i try to do this same thing for my client I get a 500 internal server error..
So here is the Workflow
On my vue frontend in the AddEngagment.vue component
<template>
<div class="page-wrapper mt-1">
<div class="add-engagement container">
<div class="card-body bg-light border-primary mb-2">
<h4 class="text-left text-primary m-0"><i class="mr-3 far fa-folder-open"></i>New Engagement</h4>
</div>
<form #submit.prevent="addEngagement" class="d-flex-column justify-content-center">
<div class="form-group">
<select class="form-control mb-3" id="type" v-model="engagement.return_type">
<option v-for="type in types" :key="type.id" :value="type">{{ type }}</option>
</select>
<input type="text" class="form-control mb-3" placeholder="Year" v-model="engagement.year">
<input type="text" class="form-control mb-3" placeholder="Assign To" v-model="engagement.assigned_to">
<input type="text" class="form-control mb-3" placeholder="Status" v-model="engagement.status">
<button type="submit" class="btn btn-lg btn-primary d-flex justify-content-start">Create</button>
</div>
</form>
</div>
</div>
</template>
<script>
export default {
name: 'add-engagement',
data() {
return {
engagement: {
return_type: null,
year: '',
assigned_to: '',
status: '',
},
types: [
'Choose Return Type...',
'1040',
'1120',
],
}
},
methods: {
addEngagement(e) {
if(!this.engagement.return_type || !this.engagement.year ){
return
} else {
this.$store.dispatch('addEngagement', {
id: this.idForEngagement,
return_type: this.engagement.return_type,
year: this.engagement.year,
assigned_to: this.engagement.assigned_to,
status: this.engagement.status,
})
e.preventDefault();
}
e.preventDefault();
this.engagement = ""
this.idForEngagement++
this.$router.push('/engagements')
},
},
created: function() {
this.engagement.return_type = this.types[0]
},
}
</script>
I am capturing the data in the input and then dispatching the store for the addEngagement action
Now in the URL for the AddEngagement.vue component I have the client_id shown like below
add-engagement/{client_id}
This is the store.js action for the addEngagement
addEngagement(context, engagement) {
axios.post(('/engagements'), {
return_type: engagement.return_type,
year: engagement.year,
assigned_to: engagement.assigned_to,
status: engagement.status,
done: false
})
.then(response => {
context.commit('getClientEngagement', response.data)
})
.catch(error => {
console.log(error)
})
},
So from here, it sends the request to my /engagement on the laravel api route file like below
Route::post('/engagements', 'EngagementsController#store');
And then goes to the EngagementsController to run the store method below
public function store($client_id, Request $request)
{
$data = $request->validate([
'return_type' => 'required|string',
'year' => 'required|string',
'status' => 'required|string',
'assigned_to' => 'required|string',
'done' => 'required|boolean'
]);
$engagement = Engagement::create([
'return_type' => $request->return_type,
'year' => $request->year,
'assigned_to' => $request->assigned_to,
'status' => $request->status,
'done' => $request->done,
+ [
'client_id' => $client_id
]
]);
return response($engagement, 201);
}
At this point is where I am getting my error and I think it has to do with the $client_id which I have tried many different ways of formatting it with no success. When the URL is storing the client_id on the front end for the post request I do not know how that data is getting shared with laravel for it to know which client the client_id foreign key will be assigned to.
First of all:
$engagement = Engagement::create([
'return_type' => $request->return_type,
'year' => $request->year,
'assigned_to' => $request->assigned_to,
'status' => $request->status,
'done' => $request->done,
+ [
'client_id' => $client_id
]
]);
why is there this +[...] array thing? Doesn't really makes sense to me...
But the 500 Server Error most probably results from your false request (which most of 500's do).
If this is your Route definition:
Route::post('/engagements', 'EngagementsController#store');
This is the method head:
public function store($client_id, Request $request)
And your Post request is the following:
axios.post(('/engagements'), {
return_type: engagement.return_type,
year: engagement.year,
assigned_to: engagement.assigned_to,
status: engagement.status,
done: false
})
You will notice, that the function definition differs from your Route. In the function you expect a parameter 'client_id' which isn't known by the route. So to resolve this issue, put your client_id into the Post request body (underneath your done: false for example) and remove the parameter from the function definition.

I can not save values using POST method - laravel vue

I'm trying to save the data I send from the Event view. in the storeEvent method of the EventController driver but it gives me error 422 and I can not find the problem so far.
The Event model has a many-to-many relationship with the Categories model, and Event also has a many-to-many relationship with the Coins model, which is why I occupy vue-multiselect since the user can select several categories or several coins for the same event
Event.vue
<template>
<form v-on:submit.prevent="createdEvent" class="form-horizontal">
<div class="form-group row">
<label>Titulo</label>
<input type="text" name="title" maxlength="25" v-model="title">
</div>
<div class="form-group row">
<label>*Cryptodivisas</label>
<multiselect v-model="coinvalue" :options="coins"
:multiple="true" label="name"
track-by="id" placeholder="Seleccione">
</multiselect>
</div>
<div class="form-group row">
<label>*Categoría</label>
<multiselect v-model="categoryvalue" :options="categories"
:multiple="true" label="name"
track-by="id" placeholder="Seleccione">
</multiselect>
</div>
<div class="col-sm-12">
<button class="btn" type="submit">Crear evento</button>
</div>
</form>
<script>
import Multiselect from 'vue-multiselect';
export default {
components: {
Multiselect,
},
props: ['auth'],
data () {
return {
user: {},
title: '',
coins: [],
coinvalue: [],
categories: [],
categoryvalue: [],
}
},
created() {
this.getCoins();
this.getCategories();
},
mounted() {
this.user = JSON.parse(this.auth);
},
methods: {
getCoins(){
let urlCoin = '/dashboard/coins';
axios.get(urlCoin)
.then((response) => {
this.coins = response.data;
})
.catch((err) => {
})
},
getCategories(){
let urlCategories = '/dashboard/categories';
axios.get(urlCategories)
.then((response) => {
this.categories = response.data;
})
.catch((err) => {
})
},
createdEvent(){
let urlEvent = '/dashboard/newEvent';
const eventData = {
'id' : this.user.id,
'title' : this.title,
'coin' : this.coinvalue,
'category' : this.categoryvalue,
}
console.log(eventData);
axios.post(urlEvent, eventData)
.then((response) => {
console.log(ok);
})
.catch((err) => {
console.log(err.response.data);
})
}
</script>
storeEvent (EventController)
public function storeEvent(Request $request)
{
$this->validate($request, [
'title' => 'required|max:25',
'coin' => 'required',
'category' => 'required',
]);
$userAuth = Auth::user()->id;
$userEvent = $request->id;
if($userAuth === $userEvent){
$event = new Event;
$event->user_id = $userEvent;
$event->title = $request->title;
if($event->save()){
$event->coins()->attach($request->coin);
$event->categories()->attach($request->category);
return response()->json([
'status' => 'Muy bien!',
'msg' => 'Tu evento ya fue creado con éxito.',
], 200);
}
else {
return response()->json([
'status' => 'Error!',
'msg' => 'No pudimos crear tu evento.',
], 401);
}
}
}
I think the problem may be when I assign the values to the coin () -> attach () and category () -> attach () section, but I have no idea how to solve it due to my inexperience in the tool.
The system was made entirely in Laravel and it worked without problems, now that it is being updated with Vue it began to give inconveniences.
Any ideas? I occupy Laravel 5,6, Vuejs 2, Axios and Vue-multiselect 2
Try sending form data
Here is the example for you.
var urlEvent = '/dashboard/newEvent';
var form_data = new FormData();
form_data.append('id',this.user.id);
form_data.append('title',this.title);
for(let coin of this.coinvalue)
form_data.append('coin[]', coin);
for(let category of this.categoryvalue)
form_data.append('category[]', category);
axios(urlEvent,{
method: "post",
data: form_data
})
.then(res => {
console.log(ok);
})
.catch(err => {
console.log(err.response.data);
});
If this stills gives you a 422 status code (Unprocessable entities). Then try returning $request in you controller. And check what data are actually send to the controller and what your validation is.
422 means validation error so do a console.log or inspect the element on axios call and check that :
'title' : this.title,
'coin' : this.coinvalue,
'category' : this.categoryvalue,
Are not empty, cause right now some data from above is missing since its a 422 validation exception.

Resources