Backend Developmentcrm

Implementing CRM System With Laravel Part 8: Contacts Module

implementing crm with laravel contacts module

In this part we will implement the most important module in a CRM system which is the contacts module which can be used to create a leads, opportunity or customer.

 

 

Series Topics:

 

As usual we will use crud generator to generate the module controller and views, then we will modify those files to make them work properly.

Generate the views:

Run this command in terminal:

php artisan crud:view contacts --fields="first_name#string;middle_name#string;last_name#string;status#integer;referral_source#string;position_title#string;industry#string;project_type#string;project_description#string;company#string;description#string;budget#string;website#string;linkedin#string;address_street#string;address_city#string;address_state#string;address_country#string;address_zipcode#string;assigned_user_id#integer" --view-path="pages" --route-group=admin --form-helper=html

Generate the controller:

php artisan crud:controller ContactsController --crud-name=contacts --model-name=Contact --model-namespace="Models\\" --view-path="pages" --route-group=admin

Now i have made the the following updates to the below files:

 

Contacts Controller

app/Http/Controllers/ContactsController.php

<?php

namespace App\Http\Controllers;

use App\Helpers\MailerFactory;
use App\Models\Contact;
use App\Models\ContactDocument;
use App\Models\ContactEmail;
use App\Models\ContactPhone;
use App\Models\ContactStatus;
use App\Models\Document;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ContactsController extends Controller
{

    protected $mailer;

    public function __construct(MailerFactory $mailer)
    {
        $this->middleware('admin:index-list_contacts|create-create_contact|show-view_contact|edit-edit_contact|destroy-delete_contact|getAssignContact-assign_contact', ['except' => ['store', 'update', 'postAssignContact']]);

        $this->mailer = $mailer;
    }


    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\View\View
     */
    public function index(Request $request)
    {
        $keyword = $request->get('search');
        $perPage = 25;

        if (!empty($keyword)) {
            $query = Contact::where('first_name', 'like', "%$keyword%")->orWhere('middle_name', 'like', "%$keyword%")->orWhere('last_name', 'like', "%$keyword%");
        } else {
            $query = Contact::latest();
        }

        if(\request('status_name') != null) {
            $query->where('status', '=', ContactStatus::where('name', \request('status_name'))->first()->id);
        }

        if(\request('assigned_user_id') != null) {
            $query->where('assigned_user_id', \request('assigned_user_id'));
        }

        // if not admin user show contacts if assigned to or created by that user
        if(Auth::user()->is_admin == 0) {

            $query->where(function ($query) {
                $query->where('assigned_user_id', Auth::user()->id)
                    ->orWhere('created_by_id', Auth::user()->id);
            });

        }

        $contacts = $query->paginate($perPage);

        return view('pages.contacts.index', compact('contacts'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
        $data = $this->getFormData();

        list($statuses, $users, $documents) = $data;

        return view('pages.contacts.create', compact('statuses', 'users', 'documents'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function store(Request $request)
    {
        $this->do_validate($request);

        $requestData = $request->all();

        $emails = $requestData['emails'];

        $phones = $request['phones'];

        unset($requestData['emails'], $requestData['phones']);

        if(isset($requestData['documents'])) {

            $documents = $requestData['documents'];

            unset($requestData['documents']);

            $documents = array_filter($documents, function ($value) {
                return !empty($value);
            });
        }

        $requestData['created_by_id'] = Auth::user()->id;

        $contact = Contact::create($requestData);

        $emails = array_filter($emails, function ($value) {
           return !empty($value);
        });

        $phones = array_filter($phones, function ($value) {
            return !empty($value);
        });

        // insert emails & phones
        if($contact && $contact->id) {

            $this->insertEmails($emails, $contact->id);

            $this->insertPhones($phones, $contact->id);

            if(isset($documents)) {

                $this->insertDocuments($documents, $contact->id);
            }
        }

        // send notifications email
        if(getSetting("enable_email_notification") == 1 && isset($requestData['assigned_user_id'])) {

            $this->mailer->sendAssignContactEmail("Contact assigned to you", User::find($requestData['assigned_user_id']), $contact);
        }

        return redirect('admin/contacts')->with('flash_message', 'Contact added!');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     *
     * @return \Illuminate\View\View
     */
    public function show($id)
    {
        $contact = Contact::findOrFail($id);

        return view('pages.contacts.show', compact('contact'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     *
     * @return \Illuminate\View\View
     */
    public function edit($id)
    {
        $data = $this->getFormData($id);

        list($statuses, $users, $documents, $contact, $selected_documents) = $data;

        return view('pages.contacts.edit', compact('contact', 'statuses', 'users', 'documents', 'selected_documents'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @param  int  $id
     *
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function update(Request $request, $id)
    {
        $this->do_validate($request);

        $requestData = $request->all();

        $emails = $requestData['emails'];

        $phones = $request['phones'];

        unset($requestData['emails'], $requestData['phones']);

        $emails = array_filter($emails, function ($value) {
            return !empty($value);
        });

        $phones = array_filter($phones, function ($value) {
            return !empty($value);
        });

        if(isset($requestData['documents'])) {

            $documents = $requestData['documents'];

            unset($requestData['documents']);

            $documents = array_filter($documents, function ($value) {
                return !empty($value);
            });
        }

        $requestData['modified_by_id'] = Auth::user()->id;

        $contact = Contact::findOrFail($id);

        $old_assign_user_id = $contact->assigned_user_id;

        $old_contact_status = $contact->status;

        $contact->update($requestData);

        // delete emails if exist
        ContactEmail::where('contact_id', $id)->delete();

        if($emails) {

            // insert
            $this->insertEmails($emails, $id);
        }

        // delete phones if exist
        ContactPhone::where('contact_id', $id)->delete();

        if($phones) {

            // insert
            $this->insertPhones($phones, $id);
        }

        // delete documents if exist
        ContactDocument::where('contact_id', $id)->delete();

        if(isset($documents)) {

            // insert
            $this->insertDocuments($documents, $id);
        }

        // send notifications email
        if(getSetting("enable_email_notification") == 1) {

            if (isset($requestData['assigned_user_id']) && $old_assign_user_id != $requestData['assigned_user_id']) {

                $this->mailer->sendAssignContactEmail("Contact assigned to you", User::find($requestData['assigned_user_id']), $contact);
            }

            // send two emails about the contact update one for the assigned user and one for the super admin

            if($old_contact_status != $requestData['status']) {

                $super_admin = User::where('is_admin', 1)->first();

                if($super_admin->id == $contact->assigned_user_id) {
                    $this->mailer->sendUpdateContactEmail("Contact status update", User::find($contact->assigned_user_id), $contact);
                } else {
                    $this->mailer->sendUpdateContactEmail("Contact status update", User::find($contact->assigned_user_id), $contact);

                    $this->mailer->sendUpdateContactEmail("Contact status update", $super_admin, $contact);
                }
            }
        }

        return redirect('admin/contacts')->with('flash_message', 'Contact updated!');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     *
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function destroy($id)
    {
        $contact = Contact::find($id);

        Contact::destroy($id);
        
        if(getSetting("enable_email_notification") == 1) {
             $this->mailer->sendDeleteContactEmail("Contact deleted", User::find($contact->assigned_user_id), $contact);
        }

        return redirect('admin/contacts')->with('flash_message', 'Contact deleted!');
    }


    public function getAssignContact($id)
    {
        $contact = Contact::find($id);

        $users = User::where('id', '!=', $contact->assigned_user_id)->get();

        return view('pages.contacts.assign', compact('users', 'contact'));
    }


    public function postAssignContact(Request $request, $id)
    {
        $this->validate($request, [
            'assigned_user_id' => 'required'
        ]);

        $contact = Contact::find($id);

        $contact->update(['assigned_user_id' => $request->assigned_user_id]);

        if(getSetting("enable_email_notification") == 1) {
             $this->mailer->sendAssignContactEmail("Contact assigned to you", User::find($request->assigned_user_id), $contact);
        }

        return redirect('admin/contacts')->with('flash_message', 'Contact assigned!');
    }


    /**
     * do_validate
     *
     *
     * @param $request
     */
    protected function do_validate($request)
    {
        $this->validate($request, [
            'first_name' => 'required',
            'last_name' => 'required'
        ]);
    }


    /**
     * insert emails
     *
     *
     * @param $emails
     * @param $contact_id
     */
    protected function insertEmails($emails, $contact_id)
    {
        foreach ($emails as $email) {

            $contactEmail = new ContactEmail();

            $contactEmail->email = $email;

            $contactEmail->contact_id = $contact_id;

            $contactEmail->save();
        }
    }


    /**
     * insert phones
     *
     *
     * @param $phones
     * @param $contact_id
     */
    protected function insertPhones($phones, $contact_id)
    {
        foreach ($phones as $phone) {

            $contactPhone = new ContactPhone();

            $contactPhone->phone = $phone;

            $contactPhone->contact_id = $contact_id;

            $contactPhone->save();
        }
    }


    /**
     * insert documents
     *
     *
     * @param $documents
     * @param $contact_id
     */
    protected function insertDocuments($documents, $contact_id)
    {
        foreach ($documents as $document) {

            $contactDocument = new ContactDocument();

            $contactDocument->document_id = $document;

            $contactDocument->contact_id = $contact_id;

            $contactDocument->save();
        }
    }

    /**
     * get form data for the contacts form
     *
     *
     *
     * @param null $id
     * @return array
     */
    protected function getFormData($id = null)
    {
        $statuses = ContactStatus::all();

        $users = User::where('is_active', 1)->get();

        if(Auth::user()->is_admin == 1) {
            $documents = Document::where('status', 1)->get();
        } else {
            $super_admin = User::where('is_admin', 1)->first();

            $documents = Document::where('status', 1)->where(function ($query) use ($super_admin) {
                $query->where('created_by_id', Auth::user()->id)
                    ->orWhere('assigned_user_id', Auth::user()->id)
                    ->orWhere('created_by_id', $super_admin->id)
                    ->orWhere('assigned_user_id', $super_admin->id);
            })->get();
        }

        if($id == null) {

            return [$statuses, $users, $documents];
        }

        $contact = Contact::findOrFail($id);

        $selected_documents = $contact->documents()->pluck('document_id')->toArray();

        return [$statuses, $users, $documents, $contact, $selected_documents];
    }

}

Contacts Views

resources/views/pages/contacts/create.blade.php

@extends('layout.app')

@section('title', ' | Create contact')

@section('content')

    <section class="content-header">
        <h1>
            Create New contact
        </h1>
        <ol class="breadcrumb">
            <li><a href="{{ url('/admin/') }}"><i class="fa fa-dashboard"></i> Dashboard</a></li>
            <li><a href="{{ url('/admin/contacts') }}">Contacts</a></li>
            <li class="active">Create</li>
        </ol>
    </section>

    <section class="content">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-body">
                        <a href="{{ url('/admin/contacts') }}" title="Back"><button class="btn btn-warning btn-sm"><i class="fa fa-arrow-left" aria-hidden="true"></i> Back</button></a>
                        <br />
                        <br />

                        @if ($errors->any())
                            <ul class="alert alert-danger">
                                @foreach ($errors->all() as $error)
                                    <li>{{ $error }}</li>
                                @endforeach
                            </ul>
                        @endif

                        <form method="POST" action="{{ url('/admin/contacts') }}" accept-charset="UTF-8" enctype="multipart/form-data">
                            {{ csrf_field() }}

                            @include ('pages.contacts.form', ['formMode' => 'create'])

                        </form>

                    </div>
                </div>
            </div>
        </div>
    </section>
@endsection

@section('scripts')

    <script type="text/javascript" src="{{ url('theme/views/contacts/form.js') }}"></script>

@stop

resources/views/pages/contacts/edit.blade.php

@extends('layout.app')

@section('title', ' | Edit contact')

@section('content')


    <section class="content-header">
        <h1>
            Edit contact #{{ $contact->id }}
        </h1>
        <ol class="breadcrumb">
            <li><a href="{{ url('/admin/') }}"><i class="fa fa-dashboard"></i> Dashboard</a></li>
            <li><a href="{{ url('/admin/contacts') }}">Contacts</a></li>
            <li class="active">Edit</li>
        </ol>
    </section>

    <section class="content">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-body">
                        <a href="{{ url('/admin/contacts') }}" title="Back"><button class="btn btn-warning btn-sm"><i class="fa fa-arrow-left" aria-hidden="true"></i> Back</button></a>
                        <br />
                        <br />

                        @if ($errors->any())
                            <ul class="alert alert-danger">
                                @foreach ($errors->all() as $error)
                                    <li>{{ $error }}</li>
                                @endforeach
                            </ul>
                        @endif

                        <form method="POST" action="{{ url('/admin/contacts/' . $contact->id) }}" accept-charset="UTF-8" enctype="multipart/form-data">
                            {{ method_field('PATCH') }}
                            {{ csrf_field() }}

                            @include ('pages.contacts.form', ['formMode' => 'edit'])

                        </form>

                    </div>
                </div>
            </div>
        </div>
    </section>
@endsection

@section('scripts')

    <script type="text/javascript" src="{{ url('theme/views/contacts/form.js') }}"></script>

@stop

resources/views/pages/contacts/form.blade.php

<div class="panel panel-default">
    <div class="panel-heading">Basic info</div>
    <div class="panel-body">
        <div class="row">
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('first_name') ? 'has-error' : ''}}">
                    <label for="first_name" class="control-label">{{ 'First Name' }}</label>
                    <input class="form-control" name="first_name" type="text" id="first_name" value="{{ isset($contact->first_name) ? $contact->first_name : ''}}" >
                    {!! $errors->first('first_name', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('middle_name') ? 'has-error' : ''}}">
                    <label for="middle_name" class="control-label">{{ 'Middle Name' }}</label>
                    <input class="form-control" name="middle_name" type="text" id="middle_name" value="{{ isset($contact->middle_name) ? $contact->middle_name : ''}}" >
                    {!! $errors->first('middle_name', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('last_name') ? 'has-error' : ''}}">
                    <label for="last_name" class="control-label">{{ 'Last Name' }}</label>
                    <input class="form-control" name="last_name" type="text" id="last_name" value="{{ isset($contact->last_name) ? $contact->last_name : ''}}" >
                    {!! $errors->first('last_name', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('status') ? 'has-error' : ''}}">
                    <label for="status" class="control-label">{{ 'Status' }}</label>
                    <select name="status" id="status" class="form-control">
                        @foreach($statuses as $status)
                            <option value="{{ $status->id }}" {{ isset($contact->status) && $contact->status == $status->id ? 'selected':'' }}>{{ $status->name }}</option>
                        @endforeach
                    </select>
                    {!! $errors->first('status', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('referral_source') ? 'has-error' : ''}}">
                    <label for="referral_source" class="control-label">{{ 'Referral Source' }}</label>
                    <input class="form-control" name="referral_source" type="text" id="referral_source" value="{{ isset($contact->referral_source) ? $contact->referral_source : ''}}" >
                    {!! $errors->first('referral_source', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('position_title') ? 'has-error' : ''}}">
                    <label for="position_title" class="control-label">{{ 'Position Title' }}</label>
                    <input class="form-control" name="position_title" type="text" id="position_title" value="{{ isset($contact->position_title) ? $contact->position_title : ''}}" >
                    {!! $errors->first('position_title', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('company') ? 'has-error' : ''}}">
                    <label for="company" class="control-label">{{ 'Company' }}</label>
                    <input class="form-control" name="company" type="text" id="company" value="{{ isset($contact->company) ? $contact->company : ''}}" >
                    {!! $errors->first('company', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('industry') ? 'has-error' : ''}}">
                    <label for="inductry" class="control-label">{{ 'Industry' }}</label>
                    <input class="form-control" name="industry" type="text" id="industry" value="{{ isset($contact->industry) ? $contact->industry : ''}}" >
                    {!! $errors->first('industry', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-4">
                <h4>Emails</h4>
                <div class="row">
                    <div class="col-md-10">
                        <div id="emails-wrapper">
                            @if(!isset($contact->emails) || count($contact->emails) == 0)
                                <div class="row" style="margin-top: 5px;">
                                    <div class="col-md-10">
                                        <input type="text" name="emails[]" class="form-control" value="" />
                                    </div>
                                </div>
                            @else
                                @foreach($contact->emails as $email)
                                    <div class="row" style="margin-top: 5px;">
                                        <div class="col-md-10">
                                            <input type="text" name="emails[]" class="form-control" value="{{ $email->email }}" />
                                        </div>
                                        @if($loop->iteration > 1)
                                            <div class="col-md-2"> <a href="javascript:void(0)" onclick="$(this).parent().parent().remove();"><i class="fa fa-remove"></i></a></div>
                                        @endif
                                    </div>
                                @endforeach
                            @endif
                        </div>
                    </div>
                    <div class="col-md-2">
                        <a href="javascript:void(0)" id="new_email" class="btn btn-warning btn-sm" title="add new email"><i class="fa fa-plus"></i></a>
                    </div>
                </div>
            </div>
            <div class="col-md-4">
                <h4>Phones</h4>
                <div class="row">
                    <div class="col-md-10">
                        <div id="phones-wrapper">
                            @if(!isset($contact->phones) || count($contact->phones) == 0)
                                <div class="row" style="margin-top: 5px;">
                                    <div class="col-md-10">
                                        <input type="text" name="phones[]" class="form-control" value="" />
                                    </div>
                                </div>
                            @else
                                @foreach($contact->phones as $phone)
                                    <div class="row" style="margin-top: 5px;">
                                        <div class="col-md-10">
                                            <input type="text" name="phones[]" class="form-control" value="{{ $phone->phone }}" />
                                        </div>
                                        @if($loop->iteration > 1)
                                            <div class="col-md-2"> <a href="javascript:void(0)" onclick="$(this).parent().parent().remove();"><i class="fa fa-remove"></i></a></div>
                                        @endif
                                    </div>
                                @endforeach
                            @endif
                        </div>
                    </div>
                    <div class="col-md-2">
                        <a href="javascript:void(0)" id="new_phone" class="btn btn-warning btn-sm" title="add new phone"><i class="fa fa-plus"></i></a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="panel panel-default">
    <div class="panel-heading">Project info</div>
    <div class="panel-body">
        <div class="row">
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('project_type') ? 'has-error' : ''}}">
                    <label for="project_type" class="control-label">{{ 'Project Type' }}</label>
                    <input class="form-control" name="project_type" type="text" id="project_type" value="{{ isset($contact->project_type) ? $contact->project_type : ''}}" >
                    {!! $errors->first('project_type', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('project_description') ? 'has-error' : ''}}">
                    <label for="project_description" class="control-label">{{ 'Project Description' }}</label>
                    <input class="form-control" name="project_description" type="text" id="project_description" value="{{ isset($contact->project_description) ? $contact->project_description : ''}}" >
                    {!! $errors->first('project_description', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('budget') ? 'has-error' : ''}}">
                    <label for="budget" class="control-label">{{ 'Budget' }}</label>
                    <input class="form-control" name="budget" type="text" id="budget" value="{{ isset($contact->budget) ? $contact->budget : ''}}" >
                    {!! $errors->first('budget', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
        </div>
    </div>
</div>
<div class="panel panel-default">
    <div class="panel-heading">Address info</div>
    <div class="panel-body">
        <div class="row">
            <div class="col-md-2">
                <div class="form-group {{ $errors->has('address_country') ? 'has-error' : ''}}">
                    <label for="address_country" class="control-label">{{ 'Country' }}</label>
                    <input class="form-control" name="address_country" type="text" id="address_country" value="{{ isset($contact->address_country) ? $contact->address_country : ''}}" >
                    {!! $errors->first('address_country', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-2">
                <div class="form-group {{ $errors->has('address_state') ? 'has-error' : ''}}">
                    <label for="address_state" class="control-label">{{ 'State' }}</label>
                    <input class="form-control" name="address_state" type="text" id="address_state" value="{{ isset($contact->address_state) ? $contact->address_state : ''}}" >
                    {!! $errors->first('address_state', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-2">
                <div class="form-group {{ $errors->has('address_city') ? 'has-error' : ''}}">
                    <label for="address_city" class="control-label">{{ 'City' }}</label>
                    <input class="form-control" name="address_city" type="text" id="address_city" value="{{ isset($contact->address_city) ? $contact->address_city : ''}}" >
                    {!! $errors->first('address_city', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('address_street') ? 'has-error' : ''}}">
                    <label for="address_street" class="control-label">{{ 'Street' }}</label>
                    <input class="form-control" name="address_street" type="text" id="address_street" value="{{ isset($contact->address_street) ? $contact->address_street : ''}}" >
                    {!! $errors->first('address_street', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-2">
                <div class="form-group {{ $errors->has('address_zipcode') ? 'has-error' : ''}}">
                    <label for="address_zipcode" class="control-label">{{ 'Zipcode' }}</label>
                    <input class="form-control" name="address_zipcode" type="text" id="address_zipcode" value="{{ isset($contact->address_zipcode) ? $contact->address_zipcode : ''}}" >
                    {!! $errors->first('address_zipcode', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
        </div>
    </div>
</div>
<div class="panel panel-default">
    <div class="panel-heading">Other info</div>
    <div class="panel-body">
        <div class="row">
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('website') ? 'has-error' : ''}}">
                    <label for="website" class="control-label">{{ 'Website' }}</label>
                    <input class="form-control" name="website" type="text" id="website" value="{{ isset($contact->website) ? $contact->website : ''}}" >
                    {!! $errors->first('website', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('linkedin') ? 'has-error' : ''}}">
                    <label for="linkedin" class="control-label">{{ 'Linkedin' }}</label>
                    <input class="form-control" name="linkedin" type="text" id="linkedin" value="{{ isset($contact->linkedin) ? $contact->linkedin : ''}}" >
                    {!! $errors->first('linkedin', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
            <div class="col-md-3">
                <div class="form-group {{ $errors->has('description') ? 'has-error' : ''}}">
                    <label for="description" class="control-label">{{ 'Description' }}</label>
                    <textarea class="form-control" name="description" type="text" id="description">{{ isset($contact->description) ? $contact->description : ''}}</textarea>
                    {!! $errors->first('description', '<p class="help-block">:message</p>') !!}
                </div>
            </div>
        </div>
    </div>
</div>

<div class="form-group">
    <label for="documents" class="control-label">{{ 'Documents' }} <i class="fa fa-link"></i></label>
    <select name="documents[]" id="documents" multiple class="form-control">
        @foreach($documents as $document)
            <option value="{{ $document->id }}" {{ isset($selected_documents) && in_array($document->id, $selected_documents)?"selected":"" }}>{{ $document->name }}</option>
        @endforeach
    </select>
</div>

@if(\Auth::user()->is_admin == 1)
    <div class="form-group {{ $errors->has('assigned_user_id') ? 'has-error' : ''}}">
        <label for="assigned_user_id" class="control-label">{{ 'Assigned User' }}</label>
        <select name="assigned_user_id" id="assigned_user_id" class="form-control">
            @foreach($users as $user)
                <option value="{{ $user->id }}" {{ isset($contact->assigned_user_id) && $contact->assigned_user_id == $user->id?"selected":"" }}>{{ $user->name }}</option>
            @endforeach
        </select>

        {!! $errors->first('assigned_user_id', '<p class="help-block">:message</p>') !!}
    </div>
@endif


<div class="form-group">
    <input class="btn btn-primary" type="submit" value="{{ $formMode === 'edit' ? 'Update' : 'Create' }}">
</div>

resources/views/pages/contacts/index.blade.php

@extends('layout.app')

@section('title', ' | List Contacts')

@section('content')

    <section class="content-header">
        <h1>
            Contacts
        </h1>
        <ol class="breadcrumb">
            <li><a href="{{ url('/admin') }}"><i class="fa fa-dashboard"></i> Dashboard</a></li>
            <li class="active">Contacts</li>
        </ol>
    </section>

    <section class="content">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-body">

                        @include('includes.flash_message')

                        @if(user_can("create_contact"))
                            <a href="{{ url('/admin/contacts/create') }}" class="btn btn-success btn-sm pull-right" title="Add New contact">
                                <i class="fa fa-plus" aria-hidden="true"></i> Add New
                            </a>
                        @endif

                        <form method="GET" action="{{ url('/admin/contacts') }}" accept-charset="UTF-8" class="form-inline my-2 my-lg-0" role="search">
                            <div class="input-group">
                                <input type="text" class="form-control" name="search" placeholder="Search..." value="{{ request('search') }}">
                                <span class="input-group-btn">
                                    <button class="btn btn-secondary" type="submit">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </span>
                            </div>
                        </form>

                        <br/>
                        <br/>
                        <div class="table-responsive">
                            <table class="table">
                                <thead>
                                <tr>
                                    @if(\Auth::user()->is_admin == 1)
                                        <th>#</th>
                                    @endif
                                    <th>First Name</th>
                                    <th>Middle Name</th>
                                    <th>Last Name</th>
                                    <th>Status</th>
                                    @if(\Auth::user()->is_admin == 1)
                                        <th>Created by</th>
                                    @endif
                                    <th>Assigned to</th>
                                    <th>Created at</th>
                                    <th>Actions</th>
                                </tr>
                                </thead>
                                <tbody>
                                    @foreach($contacts as $item)
                                        <tr>
                                            @if(\Auth::user()->is_admin == 1)
                                                <td>{{ $item->id }}</td>
                                            @endif
                                            <td>{{ $item->first_name }}</td>
                                            <td>{{ $item->middle_name }}</td>
                                            <td>{{ $item->last_name }}</td>
                                            <td><i class="btn bg-maroon">{{ $item->getStatus->name }}</i></td>
                                            @if(\Auth::user()->is_admin == 1)
                                                <td>{{ $item->createdBy->name }}</td>
                                            @endif
                                            <td>{{ $item->assignedTo != null ? $item->assignedTo->name : "not set" }}</td>
                                            
                                            <td>{{ $item->created_at }}</td>
                                            <td>

                                                @if(user_can('view_contact'))
                                                    <a href="{{ url('/admin/contacts/' . $item->id) }}" title="View contact"><button class="btn btn-info btn-sm"><i class="fa fa-eye" aria-hidden="true"></i> View</button></a>
                                                @endif

                                                @if(user_can('edit_contact'))
                                                    <a href="{{ url('/admin/contacts/' . $item->id . '/edit') }}" title="Edit contact"><button class="btn btn-primary btn-sm"><i class="fa fa-pencil-square-o" aria-hidden="true"></i> Edit</button></a>
                                                @endif

                                                @if(user_can('assign_contact'))
                                                    <a href="{{ url('/admin/contacts/' . $item->id . '/assign') }}" title="Assign contact"><button class="btn btn-primary btn-sm"><i class="fa fa-envelope-o" aria-hidden="true"></i> Assign</button></a>
                                                @endif

                                                @if(user_can('delete_contact'))
                                                    <form method="POST" action="{{ url('/admin/contacts' . '/' . $item->id) }}" accept-charset="UTF-8" style="display:inline">
                                                        {{ method_field('DELETE') }}
                                                        {{ csrf_field() }}
                                                        <button type="submit" class="btn btn-danger btn-sm" title="Delete contact" onclick="return confirm('Confirm delete?')"><i class="fa fa-trash-o" aria-hidden="true"></i> Delete</button>
                                                    </form>
                                                @endif
                                            </td>
                                        </tr>
                                    @endforeach
                                </tbody>
                            </table>
                            <div class="pagination-wrapper"> {!! $contacts->appends(['search' => Request::get('search')])->render() !!} </div>
                        </div>

                    </div>
                </div>
            </div>
        </div>
    </section>
@endsection

resources/views/pages/contacts/show.blade.php

@extends('layout.app')

@section('title', ' | Show contact')

@section('content')

    <section class="content-header">
        <h1>
            contact #{{ $contact->id }}
        </h1>
        <ol class="breadcrumb">
            <li><a href="{{ url('/admin/') }}"><i class="fa fa-dashboard"></i> Dashboard</a></li>
            <li><a href="{{ url('/admin/contacts') }}">Contacts</a></li>
            <li class="active">Show</li>
        </ol>
    </section>


    <section class="content">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-body">

                        <a href="{{ url('/admin/contacts') }}" title="Back"><button class="btn btn-warning btn-sm"><i class="fa fa-arrow-left" aria-hidden="true"></i> Back</button></a>

                        @if(user_can('edit_contact'))
                            <a href="{{ url('/admin/contacts/' . $contact->id . '/edit') }}" title="Edit contact"><button class="btn btn-primary btn-sm"><i class="fa fa-pencil-square-o" aria-hidden="true"></i> Edit</button></a>
                        @endif

                        @if(user_can('delete_contact'))
                            <form method="POST" action="{{ url('admin/contacts' . '/' . $contact->id) }}" accept-charset="UTF-8" style="display:inline">
                                {{ method_field('DELETE') }}
                                {{ csrf_field() }}
                                <button type="submit" class="btn btn-danger btn-sm" title="Delete contact" onclick="return confirm('Confirm delete?')"><i class="fa fa-trash-o" aria-hidden="true"></i> Delete</button>
                            </form>
                        @endif
                        <br/>
                        <br/>

                        <div class="table-responsive">
                            <table class="table">
                                <tbody>
                                    @if(\Auth::user()->is_admin == 1)
                                        <tr>
                                            <th>ID</th><td>{{ $contact->id }}</td>
                                        </tr>
                                    @endif
                                    <tr><th> First Name </th><td> {{ $contact->first_name }} </td>
                                    </tr><tr><th> Middle Name </th><td> {{ $contact->middle_name }} </td></tr>
                                    <tr><th> Last Name </th><td> {{ $contact->last_name }} </td></tr>
                                    <tr><th> Status </th><td> <i class="btn bg-maroon">{{ $contact->getStatus->name }}</i> </td></tr>
                                    <tr><th> Referral source </th><td> {{ $contact->referral_cource }} </td></tr>
                                    <tr><th> Position title </th><td> {{ $contact->position_title }} </td></tr>
                                    <tr><th> Industry </th><td> {{ $contact->industry }} </td></tr>
                                    <tr><th> Project type </th><td> {{ $contact->project_type }} </td></tr>
                                    <tr><th> Project description </th><td> {{ $contact->project_description }} </td></tr>
                                    <tr><th> Description </th><td> {{ $contact->description }} </td></tr>
                                    <tr><th> Company </th><td> {{ $contact->company }} </td></tr>
                                    <tr><th> Budget </th><td> {{ $contact->budget }} </td></tr>
                                    <tr><th> Website </th><td> {{ $contact->website }} </td></tr>
                                    <tr><th> Linkedin </th><td> {{ $contact->linkedin }} </td></tr>
                                    <tr><th> Street </th><td> {{ $contact->address_street }} </td></tr>
                                    <tr><th> City </th><td> {{ $contact->address_city }} </td></tr>
                                    <tr><th> State </th><td> {{ $contact->address_state }} </td></tr>
                                    <tr><th> Country </th><td> {{ $contact->address_country }} </td></tr>
                                    <tr><th> Zipcode </th><td> {{ $contact->address_zipcode }} </td></tr>
                                    @if(\Auth::user()->is_admin == 1)
                                        <tr><th> Created by </th><td>{{ $contact->createdBy->name }}</td></tr>
                                        <tr><th> Modified by </th><td>{{ isset($contact->modifiedBy->name)?$contact->modifiedBy->name:"" }}</td></tr>
                                    @endif

                                    <tr><th> Assigned to </th><td>{{ $contact->assignedTo != null ?$contact->assignedTo->name : "not set" }}</td></tr>
                                    <tr><th> Created at </th><td>{{ $contact->created_at }}</td></tr>
                                    <tr><th> Modified at </th><td>{{ $contact->updated_at }}</td></tr>
                                    @if($contact->emails->count() > 0)
                                        <tr><th>Emails </th> <td>{{ implode(", ", array_column($contact->emails->toArray(), "email")) }}</td></tr>
                                    @endif
                                    @if($contact->phones->count() > 0)
                                        <tr><th>Phones </th> <td>{{ implode(", ", array_column($contact->phones->toArray(), "phone")) }}</td></tr>
                                    @endif
                                    @if($contact->documents->count() > 0)
                                        <tr><th>Documents </th> <td>@foreach($contact->documents as $document) <a href="{{ url('uploads/documents/' . $document->file) }}">{{ $document->name }}</a> - @endforeach</td></tr>
                                    @endif
                                </tbody>
                            </table>
                        </div>

                    </div>
                </div>
            </div>
        </div>
    </section>
@endsection

resources/views/pages/contacts/assign.blade.php

@extends('layout.app')

@section('title', ' | Assign contact')

@section('content')

    <section class="content-header">
        <h1>
            Assign contact
        </h1>
        <ol class="breadcrumb">
            <li><a href="{{ url('/admin/') }}"><i class="fa fa-dashboard"></i> Dashboard</a></li>
            <li><a href="{{ url('/admin/contacts') }}">Contacts</a></li>
            <li class="active">Assign</li>
        </ol>
    </section>

    <section class="content">
        <div class="row">
            <div class="col-md-12">
                <div class="card">
                    <div class="card-body">
                        <a href="{{ url('/admin/contacts') }}" title="Back"><button class="btn btn-warning btn-sm"><i class="fa fa-arrow-left" aria-hidden="true"></i> Back</button></a>
                        <br />
                        <br />

                        @if ($errors->any())
                            <ul class="alert alert-danger">
                                @foreach ($errors->all() as $error)
                                    <li>{{ $error }}</li>
                                @endforeach
                            </ul>
                        @endif

                        <form method="POST" action="{{ url('/admin/contacts/' . $contact->id . '/assign') }}" accept-charset="UTF-8" enctype="multipart/form-data">
                            {{ csrf_field() }}

                            {{ method_field("put") }}

                            <div class="form-group {{ $errors->has('assigned_user_id') ? 'has-error' : ''}}">
                                <label for="assigned_user_id" class="control-label">{{ 'Assigned User' }}</label>
                                <select name="assigned_user_id" id="assigned_user_id" class="form-control">
                                    @foreach($users as $user)
                                        <option value="{{ $user->id }}">{{ $user->name }}</option>
                                    @endforeach
                                </select>

                                {!! $errors->first('assigned_user_id', '<p class="help-block">:message</p>') !!}
                            </div>

                            <div class="form-group">
                                <input class="btn btn-primary" type="submit" value="Assign">
                            </div>

                        </form>

                    </div>
                </div>
            </div>
        </div>
    </section>
@endsection

public/theme/views/contacts/form.js

/**
 * Contacts Form Api
 */

$(function () {
    $("#new_email").on("click", function (e) {
        var clone = $("#emails-wrapper .row:first-child").clone(true);

        clone.find("input[type='text']").val("");

        clone.append('<div class="col-md-2"> <a href="javascript:void(0)" onclick="$(this).parent().parent().remove();"><i class="fa fa-remove"></i></a></div>');

        $("#emails-wrapper").append(clone);
    });

    $("#new_phone").on("click", function (e) {
        var clone = $("#phones-wrapper .row:first-child").clone(true);

        clone.find("input[type='text']").val("");

        clone.append('<div class="col-md-2"> <a href="javascript:void(0)" onclick="$(this).parent().parent().remove();"><i class="fa fa-remove"></i></a></div>');

        $("#phones-wrapper").append(clone);
    });

    $("#documents").select2();
});

 

Update the sidebar

resources/views/layout/sidebar.blade.php

<!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar">
    <!-- sidebar: style can be found in sidebar.less -->
    <section class="sidebar">
        <!-- Sidebar user panel -->
        <div class="user-panel">
            <div class="pull-left image">
                @if(\Auth::user()->image != null)
                    <img src="{{ url('uploads/users/' . \Auth::user()->image) }}" class="img-circle" alt="User Image">
                @else
                    <img src="{{ url('theme/dist/img/image_placeholder.png') }}" class="img-circle" alt="User Image">
                @endif
            </div>
            <div class="pull-left info">
                <p>{{ \Auth::user()->name }}</p>
            </div>
        </div>
        <!-- sidebar menu: : style can be found in sidebar.less -->
        <ul class="sidebar-menu" data-widget="tree">
            <li class="header">MAIN NAVIGATION</li>
            <li class="{{ Request::segment(2) == ""?"active":"" }}">
                <a href="{{ url('/admin') }}">
                    <i class="fa fa-dashboard"></i> <span>Dashboard</span>
                </a>
            </li>

            @if(user_can('list_contacts'))
                <li class="treeview {{ Request::segment(2) == 'contacts'? 'active':'' }}">
                    <a href="#">
                        <i class="fa fa-address-card"></i> <span>Accounts</span>
                        <span class="pull-right-container">
                            <i class="fa fa-angle-left pull-right"></i>
                        </span>
                    </a>
                    <ul class="treeview-menu">
                        <li class="{{ Request::segment(2) == "contacts" && request('status_name') == null?"active":"" }}">
                            <a href="{{ url('/admin/contacts') }}"><i class="fa fa-list"></i> All contacts</a>
                        </li>
                        <li class="{{ Request::segment(2) == "contacts" && request('status_name') == 'Lead'?"active":"" }}">
                            <a href="{{ url('/admin/contacts?status_name=Lead') }}"><i class="fa fa-leaf"></i> Leads</a>
                        </li>
                        <li class="{{ Request::segment(2) == "contacts" && request('status_name') == 'Opportunity'?"active":"" }}">
                            <a href="{{ url('/admin/contacts?status_name=Opportunity') }}"><i class="fa fa-flag"></i> Opportunities</a>
                        </li>
                        <li class="{{ Request::segment(2) == "contacts" && request('status_name') == 'Customer'?"active":"" }}">
                            <a href="{{ url('/admin/contacts?status_name=Customer') }}"><i class="fa fa-user-circle"></i> Customers</a>
                        </li>
                        <li class="{{ Request::segment(2) == "contacts" && request('status_name') == 'Close'?"active":"" }}">
                            <a href="{{ url('/admin/contacts?status_name=Close') }}"><i class="fa fa-ban"></i> Close</a>
                        </li>
                    </ul>
                </li>
            @endif

            @if(user_can('list_documents'))
                <li class="{{ Request::segment(2) == "documents"?"active":"" }}">
                    <a href="{{ url('/admin/documents') }}">
                        <i class="fa fa-file-word-o"></i> <span>Documents</span>
                    </a>
                </li>
            @endif

            @if(\Auth::user()->is_admin == 1)
                <li class="{{ in_array(Request::segment(2), ['users', 'permissions', 'roles'])?"active":"" }} treeview">
                    <a href="#">
                        <i class="fa fa-users"></i> <span>User Managment</span>
                        <span class="pull-right-container">
                            <i class="fa fa-angle-left pull-right"></i>
                        </span>
                    </a>
                    <ul class="treeview-menu">
                        <li class="{{ Request::segment(2) == "users"?"active":"" }}">
                            <a href="{{ url('/admin/users') }}"><i class="fa fa-user-o"></i> Users</a>
                        </li>

                        <li class="{{ Request::segment(2) == "permissions"?"active":"" }}">
                            <a href="{{ url('/admin/permissions') }}"><i class="fa fa-ban"></i> Permissions</a>
                        </li>
                        <li class="{{ Request::segment(2) == "roles"?"active":"" }}">
                            <a href="{{ url('/admin/roles') }}"><i class="fa fa-list"></i> Roles</a>
                        </li>
                    </ul>
                </li>
            @endif
        </ul>
    </section>
    <!-- /.sidebar -->
</aside>

 

Update the routes

routes/web.php

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function () {

    Route::get('/', function () {
        return view('pages.home.index');
    });

    Route::resource('/users', 'UsersController');

    Route::get('/my-profile', 'UsersController@getProfile');

    Route::get('/my-profile/edit', 'UsersController@getEditProfile');

    Route::patch('/my-profile/edit', 'UsersController@postEditProfile');

    Route::resource('/permissions', 'PermissionsController');

    Route::resource('/roles', 'RolesController');

    Route::get('/users/role/{id}', 'UsersController@getRole');

    Route::put('/users/role/{id}', 'UsersController@updateRole');

    Route::resource('/documents', 'DocumentsController');

    Route::get('/documents/{id}/assign', 'DocumentsController@getAssignDocument');

    Route::put('/documents/{id}/assign', 'DocumentsController@postAssignDocument');

    Route::resource('/contacts', 'ContactsController');

    Route::get('/contacts/{id}/assign', 'ContactsController@getAssignContact');

    Route::put('/contacts/{id}/assign', 'ContactsController@postAssignContact');

    Route::get('/forbidden', function () {
        return view('pages.forbidden.forbidden_area');
    });
});

Route::get('/', function () {
   return redirect()->to('/admin');
});

Auth::routes();

Modify app/Helpers/MailerFactory.php add these functions at the end of the class

.....
.....

     /**
     * send Assign Contact Email
     *
     *
     * @param $subject
     * @param $user
     * @param $contact
     */
    public function sendAssignContactEmail($subject, $user, $contact)
    {
        try {
            $this->mailer->send("emails.assign_contact", ['user' => $user, 'contact' => $contact, 'subject' => $subject], function($message) use ($subject, $user) {

                $message->from($this->fromAddress, $this->fromName)
                    ->to($user->email)->subject($subject);

            });
        } catch (\Exception $ex) {
            die("Mailer Factory error: " . $ex->getMessage());
        }
    }


    /**
     * send Update Contact Email
     *
     *
     * @param $subject
     * @param $user
     * @param $contact
     */
    public function sendUpdateContactEmail($subject, $user, $contact)
    {
        try {
            $this->mailer->send("emails.update_contact", ['user' => $user, 'contact' => $contact, 'subject' => $subject], function($message) use ($subject, $user) {

                $message->from($this->fromAddress, $this->fromName)
                    ->to($user->email)->subject($subject);

            });
        } catch (\Exception $ex) {
            die("Mailer Factory error: " . $ex->getMessage());
        }
    }


    /**
     * send Delete Contact Email
     *
     *
     * @param $subject
     * @param $user
     * @param $contact
     */
    public function sendDeleteContactEmail($subject, $user, $contact)
    {
        try {
            $this->mailer->send("emails.delete_contact", ['user' => $user, 'contact' => $contact, 'subject' => $subject], function($message) use ($subject, $user) {

                $message->from($this->fromAddress, $this->fromName)
                    ->to($user->email)->subject($subject);

            });
        } catch (\Exception $ex) {
            die("Mailer Factory error: " . $ex->getMessage());
        }
    }

.....
.....

resources/views/emails/assign_contact.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ $subject }}</title>
</head>
<body>
<p>
    Hello {{ $user->name }},
</p>

<p>
    You have been assigned a contact, go and check them here <a href="{{ url('admin/contacts/' . $contact->id) }}"> {{ url('admin/contacts/' . $contact->id) }} </a>
</p>
</body>
</html>

resources/views/emails/update_contact.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ $subject }}</title>
</head>
<body>
<p>
    Hello {{ $user->name }},
</p>

<p>
    The contact {{ $contact->first_name . " " . $contact->last_name }} have been updated to {{ $contact->getStatus->name }} you can view it here <a href="{{ url('admin/contacts/' . $contact->id) }}"> {{ url('admin/contacts/' . $contact->id) }} </a>
</p>
</body>
</html>

resources/views/emails/delete_contact.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ $subject }}</title>
</head>
<body>
<p>
    Hello {{ $user->name }},
</p>

<p>
    The contact {{ $contact->first_name . " " . $contact->last_name }} have been deleted.
</p>
</body>
</html>

In the above code we have a lot of stuff, so at first in the listing page we make a check to list the contacts according to whether the user is super admin or not. If the user is super admin we display all contacts.

Otherwise if the user is not a super admin we list the contacts created by or assigned to the currently logged in user.

I have created a new function getFormData() to retrieve the form data for the contacts such as the documents and users to be used in case of creation and update. Note that for documents i retrieved the documents also according to whether the user is a super admin or not.

Next we updated the contacts creation form completely and separate it into sections, allso i added some javascript code to manipulate emails, phones and documents. The javascript code located in theme/views/contacts/form.js.

The store() and update() functions first do a simple validation then filters the phones, documents and emails from the main request array, save the data and finally we send some notification emails to the user.

Also we added the contacts module to the sidebar.blade.php and adjusted the permissions and the other related files to show the contacts to the authorized users only.

 

 

Continue to Part 9: tasks module>>>

 

5 1 vote
Article Rating

What's your reaction?

Excited
1
Happy
0
Not Sure
0
Confused
0

You may also like

Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Cesar Cortes
Cesar Cortes
3 years ago

Hi Wael, I’m implementing your crm-system proyect, but I am experiencing this error “Trying to get property ‘id’ of non-object” in line 46 of the ContactsController. I wish to get your advise please, thank you.