# Client

Make sure to check the `qb.lua` and `esx.lua` files for examples on how to implement the phone for your framework. They are always up to date with the latest changes.

## Step 1: Check Framework Compatibility

At the top of the file, add a check for `Config.Framework`. If it's not set to your framework, return to prevent it from loading.

```lua
if Config.Framework ~= "your-framework" then
    return
end
```

## Step 2: Wait for Player to Fully Load

Next, you need to wait for the player to load. How this is done depends on your framework. Once the player's character has loaded, set `loaded = true`. This lets the phone know that your framework has loaded, and is ready to be used.

```lua
while not ESX.PlayerLoaded do
    Wait(500)
end
```

## Step 3: Required Framework Functions

You need to implement the following functions for the phone to work with your framework.

### FreamworkNotification

Used to display notifications

```lua
function FreamworkNotification(text, notifType, length)
    notifType = notifType or "info"
    length = length or 5000
    print(text, notifType, length)
end
```

### GetClosestPlayer

Finds nearest players

```lua
function GetClosestPlayer()
    return Config.Core.Game.GetClosestPlayer()
end
```

### GetVehiclesInArea

Returns vehicles in the specified area

```lua
function GetVehiclesInArea(pos, maxRadius)
    return Config.Core.Game.GetVehiclesInArea(pos, maxRadius)
end

```

### GetClosestVehicle

Returns the closest vehicle to the player

```lua
function GetClosestVehicle(coord)
    return Config.Core.Game.GetClosestVehicle(coord)
end
```

### GetPlayersInArea

This function gets all players in the given radius.

```lua
function GetPlayersInArea(coord, maxRadius)
    return Config.Core.Game.GetPlayersInArea(coord, maxRadius)
end
```

### GetPlayerBankBalance

Returns the player's bank money

```lua
function GetPlayerBankBalance()
    local money = 0
    return money

    -- Returns the player's bank balance.
    -- Uses a promise to handle the asynchronous callback from the server.
    --[[
        local p = promise.new()

        Config.Core.Functions.TriggerCallback('gksphone:server:getPlayerBankBalance', function(balance)
            local money = 0
            if balance then
                money = math.floor(balance * 100) / 100
            end
            p:resolve(money)
        end)
    
        return Citizen.Await(p)
    --]]
end
```

### VehicleCreate

```lua
function VehicleCreate(model, coords, vehicleData)
    local createCar = CreateVehicle(model, coords.x, coords.y, coords.z, 0.0, true, false)
    SetVehicleOnGroundProperly(createCar)
    Config.Core.Game.SetVehicleProperties(createCar, vehicleData?.vehMods)
    SetFuel(createCar, vehicleData?.vehMods?.fuelLevel or 100)
    GiveKeyCar(createCar)
    SetModelAsNoLongerNeeded(model)
    return createCar
end
```

## Step 4: Required Framework Events

### Player load/unload/switching character

For character information when a character is loaded

```lua
PlayerData = {}
RegisterNetEvent('esx:playerLoaded', function(data)
    PlayerData = data
    PlayerData.identifier = PlayerData.identifier -- 'Player identifier'
    if PlayerData ~= nil then
        if PlayerData.job ~= nil then
            JobInfo.job = PlayerData.job.name
            JobInfo.job_grade = PlayerData.job.grade
            JobInfo.job_label = PlayerData.job.label
            JobInfo.job_grade_label = PlayerData.job.grade_label
            JobInfo.onDuty = PlayerData.job?.onDuty or false
            JobUpdate()
        end
    end

    if not isFirstLoaded then
        if Config.AutoOpen then
            ForceLoadPhone()
        end
    end

    isFirstLoaded = true
end)
```

When the character logs out, this closes the phone, ends calls, etc.

```lua
RegisterNetEvent('esx:onPlayerLogout', function()
    Debugprint('esx:onPlayerLogout')
    PlayerData = {}
    JobInfo.job = ""
    JobInfo.job_grade = 0
    JobInfo.job_label = ""
    JobInfo.job_grade_label = ""
    JobInfo.onDuty = false
    isFirstLoaded = false
    TriggerServerEvent("gksphone:server:playerDropped")
end)

```

### Player Die/handcuffed character

When a character dies or is handcuffed

```lua
Cuffed = false
AddEventHandler('esx:onPlayerDeath', function(data)
    if PhoneOpen == true then
        OpenPhone()
    end
    PhoneOpenBlock = true
    PhoneBlockReason = "You can't use the phone while dead, handcuffed or in last stand."
    if Incall then
        EndPhoneCall()
    end
    if MusicData and MusicData[CurrentPlayerId] then
        TriggerServerEvent('gksphone:server:musicListen', nil, nil, "pause", nil)
    end
end)

AddEventHandler("playerSpawned", function()
    PhoneBlockReason = ""
    PhoneOpenBlock = false
end)

AddEventHandler("esx:onPlayerSpawn", function()
    PhoneBlockReason = ""
    PhoneOpenBlock = false
end)

RegisterNetEvent('esx_policejob:handcuff', function()
    Cuffed = not Cuffed
    if Cuffed then
        if PhoneOpen == true then
            OpenPhone()
        end
        PhoneOpenBlock = true
        PhoneBlockReason = "You can't use the phone while dead, handcuffed or in last stand."
        if Incall then
            EndPhoneCall()
        end
    else
        PhoneBlockReason = ""
        PhoneOpenBlock = false
    end
end)

RegisterNetEvent('esx_policejob:unrestrain', function()
    PhoneBlockReason = ""
    PhoneOpenBlock = false
end)

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gkshop.org/gksphone-v2/custom-framework/client.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
