# Technical documentation — clientSalesTracking

Evidence date: 2026-10-18. Revision: `master` `5d5d307` (2020-06-24).

Connection settings are described (host, user, database name, and that the password in source is empty). Full PHP blocks are not copied.

## Architecture

Two layers live in one Git repository and are not wired together by a build:

- A Create React App UI under `src/` and `public/`.
- PHP scripts at the repository root that speak mysqli to MySQL.

The UI calls absolute URLs on `http://localhost/unity_/`. The PHP files are not inside a `unity_` directory in Git. A local web server must map that URL. That mapping is **Unknown / Requires Confirmation**.

```text
src/App.js                 routes
src/components/ListView.js GET  contactDetails.php
src/components/Card.js     GET  getClient.php?id=
                           POST update.php
userDetails.php            no caller in src/

header.php                 CORS + JSON content type
dbconnect.php              procedural mysqli  (list, get, users)
dbconnect2.php             object mysqli      (update)
MySQL database "unity"     tblClient, sysuser
```

There is no application server framework, no `composer.json`, and no reverse-proxy or container config.

## Languages and frameworks

| Layer | Version or library | Evidence |
|---|---|---|
| UI | React 16.13.1, React DOM 16.13.1 | `package.json` |
| Build | react-scripts 3.4.1 (Create React App) | `package.json` scripts `start`, `build`, `test`, `eject` |
| Routing | react-router-dom 5.2.0 (`BrowserRouter`, `Switch`, `Route`, `Link`, `useHistory`, `useParams`) | `src/App.js`, `ListView.js`, `Card.js` |
| HTTP client | axios 0.19.2 | `ListView.js`, `Card.js` |
| UI kit | bootstrap 4.5.0 CSS, react-bootstrap 1.0.1 | `App.js` imports the Bootstrap CSS; `Card.js` uses `Card`, `Button`, `Form`, `Col`, `Row`, `Container` |
| Table | react-bootstrap-table-next 4.0.3, react-bootstrap-table2-paginator 2.1.2 | `ListView.js` |
| API | PHP, mysqli | Root `*.php` |
| Database | MySQL database name `unity` on `localhost` | `dbconnect.php`, `dbconnect2.php` |

PHP version and MySQL version are **Unknown / Requires Confirmation**.

Node version is **Unknown / Requires Confirmation**. `package.json` has no `engines` field.

Declared and not imported by application code: jquery 3.5.1, datatables.net 1.10.21, react-bootstrap-table 4.3.1. Provenance: **Inferred** unused.

## Application structure

```text
contactDetails.php          list clients
dbconnect.php               procedural connection
dbconnect2.php              object connection
getClient.php               one client
header.php                  response headers
update.php                  update client
userDetails.php             list sysuser
package.json
package-lock.json
public/                     CRA index.html, manifest, icons, robots.txt
src/App.js                  routes
src/App.css                 CRA template, not imported
src/App.test.js             CRA sample test
src/index.js                render, service worker unregister
src/index.css               CRA body margin
src/serviceWorker.js        CRA helper, not registered
src/setupTests.js           jest-dom
src/components/Card.js      profile form (export name Profile)
src/components/ListView.js  client table
```

No `README`, `docs/`, tests beyond `App.test.js`, or SQL dump.

`package.json` `"name"` is `unity`, `"private": true`, `"version": "0.1.0"`.

## Routes

| Path | Element | Notes |
|---|---|---|
| `/ClientDetails` | `ListView` | Navbar "View" |
| `/edit/:id` | `Profile` (`Card.js`) via `component={Profile}` | Edit button target |
| `/` | none | Navbar only. No redirect |

Provenance: **Implemented** in `src/App.js`.

## HTTP API

All four scripts `require` `header.php` first.

Headers set:

- `Access-Control-Allow-Origin: *`
- `Access-Control-Allow-Headers: access`
- `Access-Control-Allow-Methods: POST`
- `Content-Type: application/json; charset=UTF-8`
- `Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With`

The second `Access-Control-Allow-Headers` replaces the first. `Authorization` is allowed and never read. Methods are limited to POST in the header while the UI uses GET for both reads. Simple GETs do not need a preflight; a JSON POST does. Provenance: **Implemented**.

| Script | Called by UI | SQL | Success body | Failure body |
|---|---|---|---|---|
| `contactDetails.php` | `GET http://localhost/unity_/contactDetails.php` | `SELECT * FROM tblClient`, then a fixed set of keys | JSON array | text `failed` |
| `getClient.php` | `GET .../getClient.php?id={id}` | `SELECT * FROM tblClient WHERE ClientID='{id}' LIMIT 1` | JSON object of the row, or `null` if no row | text `failed` |
| `update.php` | `POST .../update.php` with JSON | `UPDATE tblClient SET strEmail, strClient, strFax, strAddress, strTel WHERE ClientID='{id}'` | See below | Connection error string, or empty body if `client_name` is missing or the query returns a falsy result |
| `userDetails.php` | not called | `SELECT * FROM sysuser`, fixed keys | JSON array | text `failed` |

`update.php` reads `php://input` and `json_decode`s it. It updates only when `client_name` is set. Trimmed fields: `client_id`, `client_name`, `client_email`, `client_address`, `client_telNumber`, `client_fax`.

On a truthy `$conn->query` result the script calls `mysqli_num_rows` on that result. For an `UPDATE`, mysqli returns a boolean, not a result set. The `else` branch echoes `0` and `{"success":1,"msg":"User Inserted."}`. Provenance: **Implemented**.

The UI does not branch on that body. It `console.log`s it.

## Data

No schema file is in the repository. Columns below are the ones the scripts read or write. Further columns may exist because the statements use `SELECT *`. That is **Unknown / Requires Confirmation**.

### `tblClient`

| Column | List | Get (full row) | Update |
|---|---|---|---|
| `ClientID` | yes | yes, via `SELECT *` | WHERE |
| `strClient` | yes | yes | SET from `client_name` |
| `strTel` | yes | yes | SET from `client_telNumber` |
| `strFax` | yes | yes | SET from `client_fax` |
| `strEmail` | yes | yes | SET from `client_email` |
| `strAddress` | yes | yes | SET from `client_address` |
| `refPaymentType` | yes | yes if present on the row | not written |
| `txtClientJob` | yes | yes | not written |
| `dtLastEdit` | yes | yes | not written |

### `sysuser`

Columns copied into JSON by `userDetails.php`: `UserID`, `strUser`, `strLocation`, `strEmail`, `strTel`, `dtLastEdit`.

There is no foreign key in this repository between `sysuser` and `tblClient`.

## Auth

None. No session, cookie, basic auth, or bearer-token check. The database user in both connection scripts is `root` on `localhost` with an empty password, database `unity`.

Provenance: **Implemented**.

## Security

- Client id and update values are concatenated into SQL (`getClient.php`, `update.php`).
- List and user endpoints return every row to any caller.
- `getClient.php` returns the entire row.
- CORS origin is `*`.
- Database credentials are committed. They are local defaults (empty password). Whether those files were ever pointed at another host is **Unknown / Requires Confirmation**.
- `header.php` does not implement an authorisation check even though `Authorization` is an allowed request header.

## Background work, queues, storage, monitoring

Not present. No worker, cron, queue client, object storage, or metrics config is in the tree.

`src/index.js` calls `serviceWorker.unregister()`. The service worker helper is the Create React App default and is not active.

## Environment configuration

- React API URLs are string literals. No `.env` file is committed. `.gitignore` ignores `.env.local` and the usual CRA local env files, not a root `.env`.
- PHP settings are PHP assignments in `dbconnect.php` and `dbconnect2.php`, not environment variables.
- `public/robots.txt` allows all user agents (`Disallow:` empty).

## Development and testing

| Command | Script | Notes |
|---|---|---|
| `npm start` | `react-scripts start` | Dev server. Port is not set in the repo. Create React App's own default applies unless `PORT` is set in the environment |
| `npm run build` | `react-scripts build` | Output directory `build/` is gitignored |
| `npm test` | `react-scripts test` | Jest via react-scripts |
| `npm run eject` | `react-scripts eject` | Present as the CRA default. Not required to run the app |

`src/setupTests.js` imports `@testing-library/jest-dom/extend-expect`.

The only test, `src/App.test.js`, renders `App` and expects `/learn react/i`. The component tree does not contain that text. The test was not executed for this document. The mismatch is visible by reading the two files. Provenance: **Implemented**.

ESLint config is `"extends": "react-app"`. Browserslist is the Create React App 3.4 default (production: `>0.2%`, not dead, not Opera Mini; development: last one version of Chrome, Firefox, and Safari).

No PHPUnit, no lint script for PHP, no CI config (no bitbucket-pipelines file, no GitHub Actions, no Dockerfile).

## Deployment

**Unknown / Requires Confirmation.**

Nothing in Git names a server, a virtual host, a build pipeline, or a production URL. The only runtime URL is `http://localhost/unity_/`.

## Sonar files named at discovery

The onboarding task listed `sonar-project.properties` and `sonarqube_scan.bat` at the repo root. They are not in `master` at `5d5d307`. Provenance: **Unknown**.
