feature: Initial commit

This commit is contained in:
Keith Solomon
2025-09-24 12:27:25 -05:00
commit d512b1351e
10 changed files with 1498 additions and 0 deletions

84
.github/github_copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,84 @@
---
description: "Custom instructions for a PHP project without a framework, using Clean Code principles and phpcs PEAR standards (with exceptions from phpcs.xml). Enforce 4-space indentation, require docblocks for all classes, functions, and files."
applyTo: "**/*.php"
---
# GitHub Copilot Instructions for This PHP Project
Follow these guidelines to ensure code consistency and maintainability in this custom PHP project:
## 1. Coding Standards
- **Base Standard:** Adhere to [PHP_CodeSniffer (phpcs)](https://.com/squizlabs/PHP_CodeSniffer) PEAR coding standards as the default.
- **Custom Rules:** Where `phpcs.xml` is present, ensure all exceptions and overrides specified in that file take priority over default PEAR rules.
- **Indentation:** Always use **4 spaces** for indentation. Do not use tabs.
- **Line Endings:** Use Unix-style (`\n`) line endings.
- **Max Line Length:** Follow the PEAR default or any overrides set in `phpcs.xml`.
## 2. Clean Code Practices
- Write clear, self-explanatory, and intention-revealing code.
- Use meaningful variable, function, and class names. Avoid abbreviations and single-letter names except for loop counters and trivial cases.
- Functions should do one thing and be as short as practical.
- Avoid deep nesting; use early returns where possible.
- Minimize code duplication.
- Keep classes and functions focused on a single responsibility.
## 3. Documentation Standards
- **File-level Docblocks:** Every PHP file must start with a file-level docblock that describes the files purpose. Example:
```php
/**
* Short file description.
*
* Detailed description (if applicable).
*
* @package ProjectName
*/
```
- **Class Docblocks:** Each class must have a docblock describing its purpose, usage, and any relevant details.
```php
/**
* Class Description.
*
* Detailed explanation of what the class does.
*
* @package ProjectName
*/
```
- **Function/Method Docblocks:** All functions and methods must have docblocks that describe the purpose, parameters, return values, exceptions thrown, and side effects.
```php
/**
* Brief summary of what the function does.
*
* @param type $param Description of parameter.
* @return type Description of return value.
*/
```
- **Parameter and Return Types:** Where possible, use type declarations and annotate types in docblocks.
## 4. General PHP Practices
- Use strict types where possible: add `declare(strict_types=1);` at the top of files if project policy allows.
- Initialize variables before use.
- Avoid using global variables.
- Prefer `require_once` or `include_once` over their non-once counterparts.
- Use visibility (`public`, `protected`, `private`) for all class properties and methods; do not rely on defaults.
- Use namespaces if the project is organized into multiple logical components.
- Always sanitize and validate user input.
- Handle errors gracefully; avoid suppressing errors with `@`.
## 5. Testing
- There is **no testing framework** configured for this project. If writing test code, use clear assertions and keep test code separate from production code.
## 6. File and Project Structure
- Organize files logically by feature or responsibility.
- Name files and folders using `CamelCase` or `snake_case` consistently, based on existing codebase conventions.
- Avoid unnecessary dependencies or framework-specific constructs.
---
**Remember:**
These instructions are specific to a non-framework PHP project using Clean Code principles, enforcing 4-space indentation, and following phpcs PEAR standards with project-specific exceptions in `phpcs.xml`. Ensure all code, including classes, functions, and files, includes complete and correct docblocks. Apply these guidelines to all PHP files in the repository.

29
.gitignore vendored Normal file
View File

@@ -0,0 +1,29 @@
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
notes/
node_modules/
vendor/
.env

8
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"workbench.colorCustomizations": {
"tree.indentGuidesStroke": "#3d92ec",
"activityBar.background": "#4B1A44",
"titleBar.activeBackground": "#69255F",
"titleBar.activeForeground": "#FDF9FC"
}
}

21
config/database.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
/**
* Database configuration file for AI Fantasy NFL.
*
* PHP version: PHP 8.3+
*
* @category Configuration
* @package AI_Fantasy_NFL
* @author Keith Solomon <keith@keithsolomon.net>
* @license https://opensource.org/licenses/MIT MIT License
* @version GIT: $Id$
* @link https://github.com/your-repo/AI_Fantasy_NFL
*/
return [
'host' => 'localhost',
'port' => 3306,
'database' => 'ff-ai',
'user' => 'ff-ai',
'password' => 'lkvQm69$3!xZ',
];

1121
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

6
package.json Normal file
View File

@@ -0,0 +1,6 @@
{
"dependencies": {
"@tailwindcss/cli": "^4.1.13",
"tailwindcss": "^4.1.13"
}
}

28
phpcs.xml Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0"?>
<ruleset name="Coding Style Checks">
<description>Coding Style Checks</description>
<ini name="error_reporting" value="E_ALL &#38; ~E_DEPRECATED" />
<arg value="sp"/>
<arg name="colors"/>
<arg name="extensions" value="php,html,css"/>
<arg name="parallel" value="2048"/>
<exclude-pattern>vendor/</exclude-pattern>
<exclude-pattern>node_modules/</exclude-pattern>
<rule ref="PEAR">
<exclude name="PEAR.Classes.ClassDeclaration"/>
<exclude name="PEAR.Functions.FunctionDeclaration"/>
<exclude name="Generic.WhiteSpace.DisallowSpaceIndent.SpacesUsed"/>
<exclude name="Generic.Functions.CallTimePassByReference"/>
<exclude name="Squiz.Commenting.FileComment.MissingPackageTag"/>
<exclude name="Squiz.Commenting.FileComment.Missing"/>
<exclude name="Squiz.Commenting.FileComment.WrongStyle"/>
<exclude name="Squiz.Commenting.InlineComment.InvalidEndChar"/>
</rule>
<rule ref="Internal.NoCodeFound">
<severity>0</severity>
</rule>
</ruleset>

12
public/index.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="./output.css" rel="stylesheet">
<title>AI Fantasy NFL</title>
</head>
<body>
<h1 class="text-3xl font-bold underline">Hello world!</h1>
</body>
</html>

188
public/output.css Normal file
View File

@@ -0,0 +1,188 @@
/*! tailwindcss v4.1.13 | MIT License | https://tailwindcss.com */
@layer properties;
@layer theme, base, components, utilities;
@layer theme {
:root, :host {
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
--text-3xl: 1.875rem;
--text-3xl--line-height: calc(2.25 / 1.875);
--font-weight-bold: 700;
--default-font-family: var(--font-sans);
--default-mono-font-family: var(--font-mono);
}
}
@layer base {
*, ::after, ::before, ::backdrop, ::file-selector-button {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
html, :host {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
font-feature-settings: var(--default-font-feature-settings, normal);
font-variation-settings: var(--default-font-variation-settings, normal);
-webkit-tap-highlight-color: transparent;
}
hr {
height: 0;
color: inherit;
border-top-width: 1px;
}
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
h1, h2, h3, h4, h5, h6 {
font-size: inherit;
font-weight: inherit;
}
a {
color: inherit;
-webkit-text-decoration: inherit;
text-decoration: inherit;
}
b, strong {
font-weight: bolder;
}
code, kbd, samp, pre {
font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
font-feature-settings: var(--default-mono-font-feature-settings, normal);
font-variation-settings: var(--default-mono-font-variation-settings, normal);
font-size: 1em;
}
small {
font-size: 80%;
}
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
:-moz-focusring {
outline: auto;
}
progress {
vertical-align: baseline;
}
summary {
display: list-item;
}
ol, ul, menu {
list-style: none;
}
img, svg, video, canvas, audio, iframe, embed, object {
display: block;
vertical-align: middle;
}
img, video {
max-width: 100%;
height: auto;
}
button, input, select, optgroup, textarea, ::file-selector-button {
font: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
letter-spacing: inherit;
color: inherit;
border-radius: 0;
background-color: transparent;
opacity: 1;
}
:where(select:is([multiple], [size])) optgroup {
font-weight: bolder;
}
:where(select:is([multiple], [size])) optgroup option {
padding-inline-start: 20px;
}
::file-selector-button {
margin-inline-end: 4px;
}
::placeholder {
opacity: 1;
}
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
::placeholder {
color: currentcolor;
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, currentcolor 50%, transparent);
}
}
}
textarea {
resize: vertical;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-date-and-time-value {
min-height: 1lh;
text-align: inherit;
}
::-webkit-datetime-edit {
display: inline-flex;
}
::-webkit-datetime-edit-fields-wrapper {
padding: 0;
}
::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
padding-block: 0;
}
::-webkit-calendar-picker-indicator {
line-height: 1;
}
:-moz-ui-invalid {
box-shadow: none;
}
button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
appearance: button;
}
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
height: auto;
}
[hidden]:where(:not([hidden="until-found"])) {
display: none !important;
}
}
@layer utilities {
.text-3xl {
font-size: var(--text-3xl);
line-height: var(--tw-leading, var(--text-3xl--line-height));
}
.font-bold {
--tw-font-weight: var(--font-weight-bold);
font-weight: var(--font-weight-bold);
}
.underline {
text-decoration-line: underline;
}
}
@property --tw-font-weight {
syntax: "*";
inherits: false;
}
@layer properties {
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
*, ::before, ::after, ::backdrop {
--tw-font-weight: initial;
}
}
}

1
src/input.css Normal file
View File

@@ -0,0 +1 @@
@import "tailwindcss";