Compare commits

13 Commits

Author SHA1 Message Date
Ümit Tunç 847b99ea7b docs: update README with project information and usage instructions 2026-04-27 18:15:26 +03:00
Ümit Tunç 70fd2469be docs: update project documentation in README.md 2026-04-27 18:10:33 +03:00
Ümit Tunç f3453783e2 docs: update project documentation in README.md 2026-04-27 18:09:30 +03:00
Ümit Tunç 69debeeffd feat: add restart script for automated deployment and container lifecycle management 2026-04-27 17:54:02 +03:00
Ümit Tunç 266447e03d fix: improve API error handling, add fallback UI, and optimize Nginx connection settings 2026-04-07 15:59:30 +03:00
Ümit Tunç 747043d616 Update Docker Compose configuration for service port changes
- Changed the web service port mapping from 8088 to 8089 to avoid conflicts.
- Updated the database service port mapping from 3307 to 3308 for better alignment with application requirements.

These changes improve the accessibility and organization of the Docker setup for the Truncgil Finance application.
2025-10-25 17:10:02 -03:00
Ümit Tunç be9d6e3687 Update endpoint responses and configuration for currency, gold, and crypto rates
- Updated response content for endpoints to reflect current rates as of September 15, 2025, including changes in currency and gold prices.
- Modified example values for URL parameters to improve clarity and consistency.
- Changed the theme configuration in the Scribe documentation from 'elements' to 'scalar' for better presentation.
- Refactored the HTML structure in the Scribe index view to streamline the layout and improve accessibility.

These changes collectively enhance the accuracy and usability of the API documentation and responses in the Truncgil Finance application.
2025-09-15 11:14:02 -03:00
Ümit Tunç 15abebe9ed Update Nginx configuration for enhanced security and performance
- Changed file permissions for default.conf to improve security.
- Added security headers (X-Frame-Options, X-XSS-Protection, X-Content-Type-Options) to enhance protection against common vulnerabilities.
- Included additional parameters for PHP processing to support HTTPS and improve handling of requests.
- Implemented restrictions to deny access to hidden files and log files, further securing the application.

These changes collectively strengthen the security posture and performance of the Nginx configuration for the Truncgil Finance application.
2025-09-15 11:06:34 -03:00
Ümit Tunç beaac25180 Update Docker configuration for service port and cleanup
- Changed the web service port mapping from 8081 to 8088 for better alignment with application requirements.
- Removed unnecessary NTP installation and commands from the Dockerfile to streamline the build process.

These changes enhance the Docker setup for the Truncgil Finance application by improving service accessibility and optimizing the build configuration.
2025-09-15 11:06:16 -03:00
Ümit Tunç b494d45ed8 Add currency test data and enhance FetchCurrencyRates job with TCMB integration
- Introduced a new JSON file containing currency rates for various currencies, including USD, EUR, and GBP, to standardize currency data representation.
- Enhanced the FetchCurrencyRates job to fetch USD data from TCMB if not available, improving data reliability.
- Added logging for TCMB data fetching process to assist in monitoring and debugging.

These changes collectively improve the accuracy and robustness of currency rate handling in the Truncgil Finance application.
2025-07-05 09:48:07 +03:00
Ümit Tunç 41eaf7c6df Update gold rate naming convention in FetchGoldRates job
- Changed the abbreviation for "22AYARBILEZIK" from "YIB" to "YIA" to improve clarity and consistency in the naming convention for gold rates.

This change enhances the accuracy of the data representation in the FetchGoldRates job within the Truncgil Finance application.
2025-04-22 10:36:45 +03:00
Ümit Tunç 6ddf932bea Update docker-compose configuration for improved service management
- Added 'restart: always' policy to the app and web services to ensure they restart automatically on failure.
- Changed network names from 'laravel-network' to 'app-network' for better clarity and consistency.
- Updated the network configuration to use a bridge driver for improved networking capabilities.

These changes enhance the reliability and organization of the Docker setup for the Truncgil Finance application.
2025-04-22 10:15:39 +03:00
Ümit Tunç 93c7f74356 Enhance FetchGoldRates job with improved data handling and logging
- Added logging for data-socket-key values to assist in debugging and monitoring.
- Refined the extraction of gold rates to include specific metal types (Gold, Palladium, Platinum, Silver) based on the data attributes.
- Updated the user agent and accept language headers for improved compatibility with the data source.
- Enhanced the naming convention for gold rates to ensure clarity and consistency in the data structure.

These changes collectively improve the functionality and maintainability of the FetchGoldRates job in the Truncgil Finance application.
2025-04-22 10:15:14 +03:00
22 changed files with 349 additions and 158 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -29,7 +29,7 @@ endpoints:
responses: responses:
- -
status: 200 status: 200
content: '{"Meta_Data":{"Minutes_Ago":-0.02,"Current_Date":"2025-01-21 22:46:25","Update_Date":"2025-01-21 22:46:24"},"Rates":{"GRA":{"Selling":3140.98,"Type":"Gold","Name":"GRAMALTIN","Change":1.34,"Buying":3140.64},"GUM":{"Selling":35.28,"Type":"Gold","Name":"GUMUS","Change":0.9,"Buying":35.23},"BRE":{"Selling":0,"Type":"Gold","Name":"BRENT","Change":-0.5},"ONS":{"Buying":0,"Type":"Gold","Name":"ONS","Selling":0,"Change":1.21},"HAS":{"Buying":3125.34,"Type":"Gold","Name":"GRAMHASALTIN","Selling":3125.77,"Change":1.36},"CEY":{"Buying":4996.08,"Type":"Gold","Name":"CEYREKALTIN","Selling":5109.73,"Change":0.73},"YAR":{"Buying":9960.93,"Type":"Gold","Name":"YARIMALTIN","Selling":10219.46,"Change":0.73},"TAM":{"Buying":19984.31,"Type":"Gold","Name":"TAMALTIN","Selling":20376.41,"Change":0.73},"CUM":{"Buying":20709,"Type":"Gold","Name":"CUMHURIYETALTINI","Selling":21022,"Change":0.77},"ATA":{"Buying":20608.82,"Type":"Gold","Name":"ATAALTIN","Selling":21126.46,"Change":0.73},"ODA":{"Buying":1779.85,"Type":"Gold","Name":"14AYARALTIN","Selling":1781.37,"Change":0.73},"OSA":{"Buying":2279.46,"Type":"Gold","Name":"18AYARALTIN","Selling":2281.41,"Change":0.73},"YIA":{"Buying":2847.76,"Type":"Gold","Name":"22AYARBILEZIK","Selling":2850.2,"Change":0.73},"IKI":{"Buying":49960.78,"Type":"Gold","Name":"IKIBUCUKALTIN","Selling":50753.51,"Change":0.73},"BES":{"Buying":101170.59,"Type":"Gold","Name":"BESLIALTIN","Selling":103132.13,"Change":0.73},"GRE":{"Buying":49960.78,"Type":"Gold","Name":"GREMSEALTIN","Selling":51097.28,"Change":0.73},"RES":{"Buying":20608.82,"Type":"Gold","Name":"RESATALTIN","Selling":21126.46,"Change":0.73},"HAM":{"Buying":20608.82,"Type":"Gold","Name":"HAMITALTIN","Selling":21126.46,"Change":0.73},"GPL":{"Buying":1081.39,"Type":"Gold","Name":"GRAMPLATIN","Selling":1085.18,"Change":-0.4}}}' content: '{"Meta_Data":{"Minutes_Ago":-0.01,"Current_Date":"2025-09-15 17:13:46","Update_Date":"2025-09-15 17:13:46"},"Rates":{"GRA":{"Selling":4858.08,"Type":"Gold","Name":"GRAMALTIN","Change":0.26,"Buying":4857.61},"XU100":{"Selling":10931.75,"Type":"Gold","Name":"XU100","Change":5.4},"DBITCOIN":{"Selling":0,"Type":"Gold","Name":"DBITCOIN","Change":-0.87},"GUMUS":{"Selling":56.07,"Type":"Gold","Name":"GUMUS","Change":-0.12,"Buying":56.03},"BRENT":{"Selling":0,"Type":"Gold","Name":"BRENT","Change":0.99},"ONS":{"Buying":0,"Type":"Gold","Name":"ONS","Selling":0,"Change":0.45},"HAS":{"Buying":4833.32,"Type":"Gold","Name":"GRAMHASALTIN","Selling":4833.79,"Change":0.26},"CEYREKALTIN":{"Buying":7891.66,"Type":"Gold","Name":"CEYREKALTIN","Selling":8071.59,"Change":0.01},"YARIMALTIN":{"Buying":15734,"Type":"Gold","Name":"YARIMALTIN","Selling":16143.19,"Change":0.01},"TAMALTIN":{"Buying":31566.65,"Type":"Gold","Name":"TAMALTIN","Selling":32187.64,"Change":0.01},"CUMHURIYETALTINI":{"Buying":32651,"Type":"Gold","Name":"CUMHURIYETALTINI","Selling":33144,"Change":-0.13},"ATAALTIN":{"Buying":32553.11,"Type":"Gold","Name":"ATAALTIN","Selling":33372.46,"Change":0.01},"14AYARALTIN":{"Buying":2811.4,"Type":"Gold","Name":"14AYARALTIN","Selling":2813.95,"Change":0.01},"18AYARALTIN":{"Buying":3600.57,"Type":"Gold","Name":"18AYARALTIN","Selling":3603.83,"Change":0.01},"YIA":{"Buying":4498.25,"Type":"Gold","Name":"22AYARBILEZIK","Selling":4502.32,"Change":0.01},"IKIBUCUKALTIN":{"Buying":78916.62,"Type":"Gold","Name":"IKIBUCUKALTIN","Selling":80172.88,"Change":0.01},"BESLIALTIN":{"Buying":159806.16,"Type":"Gold","Name":"BESLIALTIN","Selling":162912.88,"Change":0.01},"GREMSEALTIN":{"Buying":78916.62,"Type":"Gold","Name":"GREMSEALTIN","Selling":80715.93,"Change":0.01},"RESATALTIN":{"Buying":32553.11,"Type":"Gold","Name":"RESATALTIN","Selling":33372.46,"Change":0.01},"HAMITALTIN":{"Buying":32553.11,"Type":"Gold","Name":"HAMITALTIN","Selling":33372.46,"Change":0.01},"GPL":{"Buying":1849.92,"Type":"Platinum","Name":"GRAMPLATIN","Selling":1854.44,"Change":-0.58},"PAL":{"Buying":1563.23,"Type":"Palladium","Name":"GRAMPALADYUM","Selling":1567.85,"Change":-1.93}}}'
headers: headers:
cache-control: 'no-cache, private' cache-control: 'no-cache, private'
content-type: application/json content-type: application/json
@@ -63,14 +63,14 @@ endpoints:
name: goldName name: goldName
description: '' description: ''
required: true required: true
example: porro example: rerum
type: string type: string
enumValues: [] enumValues: []
exampleWasSpecified: false exampleWasSpecified: false
nullable: false nullable: false
custom: [] custom: []
cleanUrlParameters: cleanUrlParameters:
goldName: porro goldName: rerum
queryParameters: [] queryParameters: []
cleanQueryParameters: [] cleanQueryParameters: []
bodyParameters: [] bodyParameters: []
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -29,7 +29,7 @@ endpoints:
responses: responses:
- -
status: 200 status: 200
content: '{"server_time":"22:46:25"}' content: '{"server_time":"17:13:46"}'
headers: headers:
cache-control: 'no-cache, private' cache-control: 'no-cache, private'
content-type: application/json content-type: application/json
@@ -68,7 +68,7 @@ endpoints:
responses: responses:
- -
status: 200 status: 200
content: '{"server_date":"2025-01-21"}' content: '{"server_date":"2025-09-15"}'
headers: headers:
cache-control: 'no-cache, private' cache-control: 'no-cache, private'
content-type: application/json content-type: application/json
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -27,7 +27,7 @@ endpoints:
responses: responses:
- -
status: 200 status: 200
content: '{"Meta_Data":{"Minutes_Ago":-0.02,"Current_Date":"2025-01-21 22:46:25","Update_Date":"2025-01-21 22:46:24"},"Rates":{"GRA":{"Selling":3140.98,"Type":"Gold","Name":"GRAMALTIN","Change":1.34,"Buying":3140.64},"GUM":{"Selling":35.28,"Type":"Gold","Name":"GUMUS","Change":0.9,"Buying":35.23},"BRE":{"Selling":0,"Type":"Gold","Name":"BRENT","Change":-0.5},"ONS":{"Buying":0,"Type":"Gold","Name":"ONS","Selling":0,"Change":1.21},"HAS":{"Buying":3125.34,"Type":"Gold","Name":"GRAMHASALTIN","Selling":3125.77,"Change":1.36},"CEY":{"Buying":4996.08,"Type":"Gold","Name":"CEYREKALTIN","Selling":5109.73,"Change":0.73},"YAR":{"Buying":9960.93,"Type":"Gold","Name":"YARIMALTIN","Selling":10219.46,"Change":0.73},"TAM":{"Buying":19984.31,"Type":"Gold","Name":"TAMALTIN","Selling":20376.41,"Change":0.73},"CUM":{"Buying":20709,"Type":"Gold","Name":"CUMHURIYETALTINI","Selling":21022,"Change":0.77},"ATA":{"Buying":20608.82,"Type":"Gold","Name":"ATAALTIN","Selling":21126.46,"Change":0.73},"ODA":{"Buying":1779.85,"Type":"Gold","Name":"14AYARALTIN","Selling":1781.37,"Change":0.73},"OSA":{"Buying":2279.46,"Type":"Gold","Name":"18AYARALTIN","Selling":2281.41,"Change":0.73},"YIA":{"Buying":2847.76,"Type":"Gold","Name":"22AYARBILEZIK","Selling":2850.2,"Change":0.73},"IKI":{"Buying":49960.78,"Type":"Gold","Name":"IKIBUCUKALTIN","Selling":50753.51,"Change":0.73},"BES":{"Buying":101170.59,"Type":"Gold","Name":"BESLIALTIN","Selling":103132.13,"Change":0.73},"GRE":{"Buying":49960.78,"Type":"Gold","Name":"GREMSEALTIN","Selling":51097.28,"Change":0.73},"RES":{"Buying":20608.82,"Type":"Gold","Name":"RESATALTIN","Selling":21126.46,"Change":0.73},"HAM":{"Buying":20608.82,"Type":"Gold","Name":"HAMITALTIN","Selling":21126.46,"Change":0.73},"GPL":{"Buying":1081.39,"Type":"Gold","Name":"GRAMPLATIN","Selling":1085.18,"Change":-0.4}}}' content: '{"Meta_Data":{"Minutes_Ago":-0.01,"Current_Date":"2025-09-15 17:13:46","Update_Date":"2025-09-15 17:13:46"},"Rates":{"GRA":{"Selling":4858.08,"Type":"Gold","Name":"GRAMALTIN","Change":0.26,"Buying":4857.61},"XU100":{"Selling":10931.75,"Type":"Gold","Name":"XU100","Change":5.4},"DBITCOIN":{"Selling":0,"Type":"Gold","Name":"DBITCOIN","Change":-0.87},"GUMUS":{"Selling":56.07,"Type":"Gold","Name":"GUMUS","Change":-0.12,"Buying":56.03},"BRENT":{"Selling":0,"Type":"Gold","Name":"BRENT","Change":0.99},"ONS":{"Buying":0,"Type":"Gold","Name":"ONS","Selling":0,"Change":0.45},"HAS":{"Buying":4833.32,"Type":"Gold","Name":"GRAMHASALTIN","Selling":4833.79,"Change":0.26},"CEYREKALTIN":{"Buying":7891.66,"Type":"Gold","Name":"CEYREKALTIN","Selling":8071.59,"Change":0.01},"YARIMALTIN":{"Buying":15734,"Type":"Gold","Name":"YARIMALTIN","Selling":16143.19,"Change":0.01},"TAMALTIN":{"Buying":31566.65,"Type":"Gold","Name":"TAMALTIN","Selling":32187.64,"Change":0.01},"CUMHURIYETALTINI":{"Buying":32651,"Type":"Gold","Name":"CUMHURIYETALTINI","Selling":33144,"Change":-0.13},"ATAALTIN":{"Buying":32553.11,"Type":"Gold","Name":"ATAALTIN","Selling":33372.46,"Change":0.01},"14AYARALTIN":{"Buying":2811.4,"Type":"Gold","Name":"14AYARALTIN","Selling":2813.95,"Change":0.01},"18AYARALTIN":{"Buying":3600.57,"Type":"Gold","Name":"18AYARALTIN","Selling":3603.83,"Change":0.01},"YIA":{"Buying":4498.25,"Type":"Gold","Name":"22AYARBILEZIK","Selling":4502.32,"Change":0.01},"IKIBUCUKALTIN":{"Buying":78916.62,"Type":"Gold","Name":"IKIBUCUKALTIN","Selling":80172.88,"Change":0.01},"BESLIALTIN":{"Buying":159806.16,"Type":"Gold","Name":"BESLIALTIN","Selling":162912.88,"Change":0.01},"GREMSEALTIN":{"Buying":78916.62,"Type":"Gold","Name":"GREMSEALTIN","Selling":80715.93,"Change":0.01},"RESATALTIN":{"Buying":32553.11,"Type":"Gold","Name":"RESATALTIN","Selling":33372.46,"Change":0.01},"HAMITALTIN":{"Buying":32553.11,"Type":"Gold","Name":"HAMITALTIN","Selling":33372.46,"Change":0.01},"GPL":{"Buying":1849.92,"Type":"Platinum","Name":"GRAMPLATIN","Selling":1854.44,"Change":-0.58},"PAL":{"Buying":1563.23,"Type":"Palladium","Name":"GRAMPALADYUM","Selling":1567.85,"Change":-1.93}}}'
headers: headers:
cache-control: 'no-cache, private' cache-control: 'no-cache, private'
content-type: application/json content-type: application/json
@@ -61,14 +61,14 @@ endpoints:
name: goldName name: goldName
description: '' description: ''
required: true required: true
example: porro example: rerum
type: string type: string
enumValues: [] enumValues: []
exampleWasSpecified: false exampleWasSpecified: false
nullable: false nullable: false
custom: [] custom: []
cleanUrlParameters: cleanUrlParameters:
goldName: porro goldName: rerum
queryParameters: [] queryParameters: []
cleanQueryParameters: [] cleanQueryParameters: []
bodyParameters: [] bodyParameters: []
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -27,7 +27,7 @@ endpoints:
responses: responses:
- -
status: 200 status: 200
content: '{"server_time":"22:46:25"}' content: '{"server_time":"17:13:46"}'
headers: headers:
cache-control: 'no-cache, private' cache-control: 'no-cache, private'
content-type: application/json content-type: application/json
@@ -66,7 +66,7 @@ endpoints:
responses: responses:
- -
status: 200 status: 200
content: '{"server_date":"2025-01-21"}' content: '{"server_date":"2025-09-15"}'
headers: headers:
cache-control: 'no-cache, private' cache-control: 'no-cache, private'
content-type: application/json content-type: application/json
+59 -44
View File
@@ -1,66 +1,81 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
<p align="center"> <p align="center">
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a> <img src="public/img/logo-light.svg" width="400" alt="Truncgil Finance Logo Light" style="background-color: #333; padding: 10px; border-radius: 5px;">
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p> </p>
## About Laravel # Truncgil Finance Application
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- [Simple, fast routing engine](https://laravel.com/docs/routing). Bu proje, Truncgil bünyesinde geliştirilen Docker tabanlı bir Laravel finans uygulamasıdır. Proje; PHP 8.2-FPM, Nginx ve MySQL 8.0 servislerini içermektedir.
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
Laravel is accessible, powerful, and provides tools required for large, robust applications. ## 🚀 Hızlı Başlangıç (Kurulum)
## Learning Laravel Projeyi yerel ortamınızda veya sunucunuzda çalıştırmak için aşağıdaki adımları izleyin:
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. ### 1. Depoyu Klonlayın
```bash
git clone https://git.truncgil.com/truncgit/finance.git
cd finance
```
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch. ### 2. Yapılandırma Dosyasını Hazırlayın
`.env.example` dosyasını `.env` olarak kopyalayın ve gerekli düzenlemeleri yapın:
```bash
cp .env.example .env
```
> **Önemli:** Docker içerisinde çalışırken `DB_HOST=db` ve `DB_PORT=3306` (docker iç ağı için) olarak ayarlanmalıdır. Dışarıdan erişim için Docker 3308 portunu kullanmaktadır.
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. ### 3. Servisleri Başlatın
Proje içerisinde bulunan `restart.sh` betiği, port çakışmalarını kontrol eder, eski konteynerleri temizler ve sistemi Docker Compose ile ayağa kaldırır:
```bash
chmod +x restart.sh
./restart.sh
```
## Laravel Sponsors ### 4. Uygulamaya Erişin
Servisler başarıyla başlatıldıktan sonra tarayıcınızdan şu adrese gidebilirsiniz:
- **Uygulama:** [http://localhost:8089](http://localhost:8089)
- **Veritabanı (Dış Erişim):** localhost:3308
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com). ---
### Premium Partners ## 🛠️ Nasıl Çalışır? (Mimari)
- **[Vehikl](https://vehikl.com/)** Proje, modern konteynerleştirme standartlarına uygun olarak tasarlanmıştır:
- **[Tighten Co.](https://tighten.co)**
- **[WebReinvent](https://webreinvent.com/)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[DevSquad](https://devsquad.com/hire-laravel-developers)**
- **[Jump24](https://jump24.co.uk)**
- **[Redberry](https://redberry.international/laravel/)**
- **[Active Logic](https://activelogic.com)**
- **[byte5](https://byte5.de)**
- **[OP.GG](https://op.gg)**
## Contributing ### Servis Yapısı
- **app:** PHP 8.2-FPM üzerinde koşan Laravel uygulamasıdır. `dockerfile` içerisinde gerekli PHP eklentileri (pdo_mysql, bcmath, gd vb.) ve otomatik görevler (cron) yapılandırılmıştır.
- **web:** Nginx (alpine) sunucusudur. Gelen istekleri karşılar ve PHP servisine yönlendirir.
- **db:** MySQL 8.0 veritabanıdır. Veriler `db_data` volume'ü içerisinde kalıcı olarak saklanır.
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). ### Otomatik Görevler (Cron)
`dockerfile` içerisinde tanımlanan cron yapısı ile Laravel'in `artisan run-all-fetchs` komutu her dakika otomatik olarak çalıştırılır. Bu, finansal verilerin güncel tutulmasını sağlar.
## Code of Conduct ### API Dokümantasyonu
Proje içerisinde **Scribe** kullanılmaktadır. `dockerfile` build aşamasında API dokümantasyonu otomatik olarak üretilir.
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). ---
## Security Vulnerabilities ## 💻 Faydalı Komutlar
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. Aşağıdaki komutları konteyner içerisinde çalıştırmak için `docker exec` kullanabilirsiniz:
## License **Migrasyonları Çalıştır:**
```bash
docker exec -it truncgil-finance-app php artisan migrate
```
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). **Verileri Seed Et:**
```bash
docker exec -it truncgil-finance-app php artisan db:seed
```
**Logları Takip Et:**
```bash
docker compose -p finance logs -f
```
---
## 📝 Notlar
- Uygulama anahtarı (`APP_KEY`) ilk build sırasında otomatik olarak üretilir.
- Port veya servis isimlerini değiştirmek isterseniz `docker-compose.yml` ve `restart.sh` dosyalarını güncelleyebilirsiniz.
+94 -1
View File
@@ -20,7 +20,7 @@ class FetchCurrencyRates implements ShouldQueue
$data = []; $data = [];
$data['Update_Date'] = now()->format('Y-m-d H:i:s'); $data['Update_Date'] = now()->format('Y-m-d H:i:s');
// Döviz kurları // Döviz kurları - ana kaynak
$response = $this->fetchData('https://kur.doviz.com'); $response = $this->fetchData('https://kur.doviz.com');
// DOM işlemleri için veri çekme // DOM işlemleri için veri çekme
@@ -53,11 +53,24 @@ class FetchCurrencyRates implements ShouldQueue
} }
} }
// Eğer USD verisi yoksa veya boşsa, TCMB'den veri çek
if (!isset($data['USD']) || empty($data['USD']['Buying'])) {
\Log::info('USD verisi bulunamadı, TCMB\'den veri çekiliyor...');
$tcmbData = $this->fetchFromTCMB();
if (!empty($tcmbData)) {
\Log::info('TCMB\'den ' . count($tcmbData) . ' kur alındı');
$data = array_merge($data, $tcmbData);
} else {
\Log::error('TCMB\'den veri alınamadı');
}
}
// AZN kuru için // AZN kuru için
$aznResponse = $this->fetchData('https://wise.com/tr/currency-converter/azn-to-try-rate?amount=1'); $aznResponse = $this->fetchData('https://wise.com/tr/currency-converter/azn-to-try-rate?amount=1');
preg_match('/(\d+\.\d+)\s+TRY/', $aznResponse->body(), $matches); preg_match('/(\d+\.\d+)\s+TRY/', $aznResponse->body(), $matches);
if (isset($matches[1])) { if (isset($matches[1])) {
$data['AZN'] = [ $data['AZN'] = [
'Name' => 'AZERBAYCAN YENİ MANATI',
'Buying' => NumberFormatter::commaToDot($matches[1]), 'Buying' => NumberFormatter::commaToDot($matches[1]),
'Selling' => NumberFormatter::commaToDot($matches[1]), 'Selling' => NumberFormatter::commaToDot($matches[1]),
'Change' => "0.00", 'Change' => "0.00",
@@ -78,4 +91,84 @@ class FetchCurrencyRates implements ShouldQueue
'Accept-Language' => 'en' 'Accept-Language' => 'en'
])->get($url); ])->get($url);
} }
private function fetchFromTCMB()
{
try {
$response = $this->fetchData('https://www.tcmb.gov.tr/kurlar/today.xml');
if (!$response->successful()) {
return [];
}
$xml = simplexml_load_string($response->body());
if (!$xml) {
return [];
}
$data = [];
// Currency mapping - TCMB'deki isimleri kod olarak kullan
$currencyMap = [
'USD' => 'US DOLLAR',
'EUR' => 'EURO',
'GBP' => 'POUND STERLING',
'CHF' => 'SWISS FRANK',
'JPY' => 'JAPENESE YEN',
'CAD' => 'CANADIAN DOLLAR',
'AUD' => 'AUSTRALIAN DOLLAR',
'SEK' => 'SWEDISH KRONA',
'NOK' => 'NORWEGIAN KRONE',
'DKK' => 'DANISH KRONE',
'RUB' => 'RUSSIAN ROUBLE',
'CNY' => 'CHINESE RENMINBI',
'SAR' => 'SAUDI RIYAL',
'KWD' => 'KUWAITI DINAR',
'QAR' => 'QATARI RIAL',
'AED' => 'UNITED ARAB EMIRATES DIRHAM',
'PKR' => 'PAKISTANI RUPEE',
'KRW' => 'SOUTH KOREAN WON',
'AZN' => 'AZERBAIJANI NEW MANAT',
'BGN' => 'BULGARIAN LEV',
'RON' => 'NEW LEU'
];
foreach ($xml->Currency as $currency) {
$code = (string)$currency['CurrencyCode'];
$unit = (float)$currency->Unit;
$name = (string)$currency->CurrencyName;
$buying = (float)$currency->BanknoteBuying;
$selling = (float)$currency->BanknoteSelling;
$forexBuying = (float)$currency->ForexBuying;
$forexSelling = (float)$currency->ForexSelling;
// Birim düzeltmesi (100 yen = 1 birim gibi)
if ($unit > 1) {
$buying = $buying / $unit;
$selling = $selling / $unit;
$forexBuying = $forexBuying / $unit;
$forexSelling = $forexSelling / $unit;
}
// Forex kurları varsa onları kullan, yoksa banknot kurlarını kullan
$finalBuying = $forexBuying > 0 ? $forexBuying : $buying;
$finalSelling = $forexSelling > 0 ? $forexSelling : $selling;
if ($finalBuying > 0 && $finalSelling > 0) {
$data[$code] = [
'Name' => $name,
'Buying' => round($finalBuying, 4),
'Selling' => round($finalSelling, 4),
'Change' => 0.00,
'Type' => 'Currency'
];
}
}
return $data;
} catch (\Exception $e) {
return [];
}
}
} }
+44 -11
View File
@@ -10,6 +10,7 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use App\Helpers\NumberFormatter; use App\Helpers\NumberFormatter;
use Illuminate\Support\Facades\Log;
class FetchGoldRates implements ShouldQueue class FetchGoldRates implements ShouldQueue
{ {
@@ -23,30 +24,59 @@ class FetchGoldRates implements ShouldQueue
// Altın kurları // Altın kurları
$goldResponse = $this->fetchData('https://altin.doviz.com'); $goldResponse = $this->fetchData('https://altin.doviz.com');
$domGold = new \DOMDocument(); $domGold = new \DOMDocument();
@$domGold->loadHTML($goldResponse->body()); @$domGold->loadHTML($goldResponse->body());
$xpathGold = new \DOMXPath($domGold); $xpathGold = new \DOMXPath($domGold);
// Daha spesifik bir sorgu ile sadece ihtiyacımız olan elementleri seçiyoruz
$elementsGold = $xpathGold->query("//*[@data-socket-key]"); $elementsGold = $xpathGold->query("//*[@data-socket-key]");
// Debug için gelen data-socket-key değerlerini loglamak için
$socketKeys = [];
foreach ($elementsGold as $element) { foreach ($elementsGold as $element) {
$attrGold = $element->getAttribute('data-socket-key'); $attrGold = $element->getAttribute('data-socket-key');
$typeGold = $element->getAttribute('data-socket-attr'); $typeGold = $element->getAttribute('data-socket-attr');
$valueGold = NumberFormatter::commaToDot($element->nodeValue); $valueGold = NumberFormatter::commaToDot($element->nodeValue);
if (trim($attrGold) !== '') { // Debug için data-socket-key değerlerini topluyoruz
if (!in_array($attrGold, $socketKeys)) {
$socketKeys[] = $attrGold;
}
if (trim($attrGold) !== '') {
// Önce orijinal ismi tam olarak koruyalım
$nameGold = strtoupper(str_replace("-", "", $attrGold)); $nameGold = strtoupper(str_replace("-", "", $attrGold));
$fullNameGold = $nameGold; $fullNameGold = $nameGold;
$nameGold = str_replace("14", "OD", $nameGold);
$nameGold = str_replace("18", "OS", $nameGold); // Veri tipi belirlemeleri
$nameGold = str_replace("22", "YI", $nameGold); $metalType = "Gold"; // Varsayılan olarak altın
// Özel metaller için tür kontrolü
if (strpos($nameGold, 'GRAMPALADYUM') !== false) {
$metalType = "Palladium";
} elseif (strpos($nameGold, 'GRAMPLATIN') !== false) {
$metalType = "Platinum";
} elseif (strpos($nameGold, 'GRAMGUMUS') !== false) {
$metalType = "Silver";
}
// Kısaltma işlemleri
$nameGold = str_replace("14AYARBILEZIK", "ODB", $nameGold);
$nameGold = str_replace("18AYARBILEZIK", "OSB", $nameGold);
$nameGold = str_replace("22AYARBILEZIK", "YIA", $nameGold);
$nameGold = str_replace("GRAMALTIN", "GRA", $nameGold); $nameGold = str_replace("GRAMALTIN", "GRA", $nameGold);
$nameGold = str_replace("GRAMPLATIN", "GPL", $nameGold); $nameGold = str_replace("GRAMPLATIN", "GPL", $nameGold);
$nameGold = str_replace("GRAMHASALTIN", "HAS", $nameGold); $nameGold = str_replace("GRAMHASALTIN", "HAS", $nameGold);
$nameGold = strtoupper(substr($nameGold, 0, 3)); $nameGold = str_replace("GRAMPALADYUM", "PAL", $nameGold);
$nameGold = str_replace("GRAMGUMUS", "GUM", $nameGold);
// Eğer bir kısaltma yapıldıysa, ilk 3 karakteri al
// Aksi takdirde orijinal değeri kullan
if ($nameGold != $fullNameGold) {
$nameGold = strtoupper(substr($nameGold, 0, 3));
}
$except = ['USD', 'EUR', 'GBP', 'XU1', 'BIT']; $except = ['USD', 'EUR', 'GBP', 'XU1', 'BIT'];
if (in_array($nameGold, $except)) { if (in_array($nameGold, $except)) {
@@ -56,13 +86,15 @@ class FetchGoldRates implements ShouldQueue
if ($typeGold == "bid") $data[$nameGold]['Buying'] = (float)$valueGold; if ($typeGold == "bid") $data[$nameGold]['Buying'] = (float)$valueGold;
if ($typeGold == "ask") $data[$nameGold]['Selling'] = (float)$valueGold; if ($typeGold == "ask") $data[$nameGold]['Selling'] = (float)$valueGold;
if ($typeGold == "s") $data[$nameGold]['Selling'] = (float)$valueGold; if ($typeGold == "s") $data[$nameGold]['Selling'] = (float)$valueGold;
if ($typeGold == "c") $data[$nameGold]['Change'] = round((float)$valueGold, if ($typeGold == "c") $data[$nameGold]['Change'] = round((float)$valueGold, 2);
2); $data[$nameGold]['Type'] = $metalType;
$data[$nameGold]['Type'] = "Gold";
$data[$nameGold]['Name'] = $fullNameGold; $data[$nameGold]['Name'] = $fullNameGold;
} }
} }
// Debug için socket key'leri loglayalım
Log::info('Available data-socket-keys: ' . implode(', ', $socketKeys));
// JSON dosyasını kaydet // JSON dosyasını kaydet
Storage::put('gold/today.json', json_encode($data, JSON_UNESCAPED_UNICODE)); Storage::put('gold/today.json', json_encode($data, JSON_UNESCAPED_UNICODE));
@@ -72,8 +104,9 @@ class FetchGoldRates implements ShouldQueue
private function fetchData($url) private function fetchData($url)
{ {
return Http::withHeaders([ return Http::withHeaders([
'User-Agent' => 'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10', 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept-Language' => 'en' 'Accept-Language' => 'tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7',
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'
])->get($url); ])->get($url);
} }
} }
+1 -1
View File
@@ -47,7 +47,7 @@ return [
'type' => 'external_laravel', 'type' => 'external_laravel',
// See https://scribe.knuckles.wtf/laravel/reference/config#theme for supported options // See https://scribe.knuckles.wtf/laravel/reference/config#theme for supported options
'theme' => 'elements', 'theme' => 'scalar',
'static' => [ 'static' => [
// HTML documentation, assets and Postman collection will be generated to this folder. // HTML documentation, assets and Postman collection will be generated to this folder.
+1
View File
@@ -0,0 +1 @@
{"USD":{"Name":"US DOLLAR","Buying":39.6792,"Selling":39.7506,"Change":0,"Type":"Currency"},"AUD":{"Name":"AUSTRALIAN DOLLAR","Buying":25.967,"Selling":26.1363,"Change":0,"Type":"Currency"},"DKK":{"Name":"DANISH KRONE","Buying":6.2523,"Selling":6.2831,"Change":0,"Type":"Currency"},"EUR":{"Name":"EURO","Buying":46.7222,"Selling":46.8064,"Change":0,"Type":"Currency"},"GBP":{"Name":"POUND STERLING","Buying":54.1032,"Selling":54.3853,"Change":0,"Type":"Currency"},"CHF":{"Name":"SWISS FRANK","Buying":49.8917,"Selling":50.212,"Change":0,"Type":"Currency"},"SEK":{"Name":"SWEDISH KRONA","Buying":4.1341,"Selling":4.1769,"Change":0,"Type":"Currency"},"CAD":{"Name":"CANADIAN DOLLAR","Buying":29.1614,"Selling":29.293,"Change":0,"Type":"Currency"},"KWD":{"Name":"KUWAITI DINAR","Buying":129.2622,"Selling":130.9536,"Change":0,"Type":"Currency"},"NOK":{"Name":"NORWEGIAN KRONE","Buying":3.9292,"Selling":3.9556,"Change":0,"Type":"Currency"},"SAR":{"Name":"SAUDI RIYAL","Buying":10.5802,"Selling":10.5992,"Change":0,"Type":"Currency"},"JPY":{"Name":"JAPENESE YEN","Buying":0.2742,"Selling":0.276,"Change":0,"Type":"Currency"},"BGN":{"Name":"BULGARIAN LEV","Buying":23.7551,"Selling":24.0659,"Change":0,"Type":"Currency"},"RON":{"Name":"NEW LEU","Buying":9.183,"Selling":9.3032,"Change":0,"Type":"Currency"},"RUB":{"Name":"RUSSIAN ROUBLE","Buying":0.5007,"Selling":0.5073,"Change":0,"Type":"Currency"},"CNY":{"Name":"CHINESE RENMINBI","Buying":5.5081,"Selling":5.5802,"Change":0,"Type":"Currency"},"PKR":{"Name":"PAKISTANI RUPEE","Buying":0.139,"Selling":0.1408,"Change":0,"Type":"Currency"},"QAR":{"Name":"QATARI RIAL","Buying":10.8255,"Selling":10.9671,"Change":0,"Type":"Currency"},"KRW":{"Name":"SOUTH KOREAN WON","Buying":0.0289,"Selling":0.0293,"Change":0,"Type":"Currency"},"AZN":{"Name":"AZERBAIJANI NEW MANAT","Buying":23.2099,"Selling":23.5136,"Change":0,"Type":"Currency"},"AED":{"Name":"UNITED ARAB EMIRATES DIRHAM","Buying":10.7422,"Selling":10.8828,"Change":0,"Type":"Currency"}}
Regular → Executable
+9 -6
View File
@@ -6,21 +6,23 @@ services:
dockerfile: dockerfile dockerfile: dockerfile
image: truncgil-finance-app:latest image: truncgil-finance-app:latest
container_name: truncgil-finance-app container_name: truncgil-finance-app
restart: always
volumes: volumes:
- .:/var/www - .:/var/www
networks: networks:
- laravel-network - app-network
web: web:
image: nginx:alpine image: nginx:alpine
container_name: truncgil-finance-web container_name: truncgil-finance-web
restart: always
ports: ports:
- "8081:80" - "8089:80"
volumes: volumes:
- .:/var/www - .:/var/www
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
networks: networks:
- laravel-network - app-network
db: db:
image: mysql:8.0 image: mysql:8.0
@@ -34,12 +36,13 @@ services:
volumes: volumes:
- db_data:/var/lib/mysql - db_data:/var/lib/mysql
networks: networks:
- laravel-network - app-network
ports: ports:
- "3307:3306" - "3308:3306"
networks: networks:
laravel-network: app-network:
driver: bridge
volumes: volumes:
db_data: db_data:
-3
View File
@@ -15,10 +15,7 @@ RUN apt-get update && apt-get install -y \
libxml2-dev \ libxml2-dev \
zip \ zip \
cron \ cron \
ntp \
&& service cron start && \ && service cron start && \
ntpd -gq && \
ntpd && \
docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd \ docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd \
&& echo "* * * * * cd /var/www && php /var/www/artisan run-all-fetchs >> /dev/null 2>&1" >> /etc/cron.d/laravel-cron \ && echo "* * * * * cd /var/www && php /var/www/artisan run-all-fetchs >> /dev/null 2>&1" >> /etc/cron.d/laravel-cron \
&& chmod 0644 /etc/cron.d/laravel-cron \ && chmod 0644 /etc/cron.d/laravel-cron \
Regular → Executable
+47 -6
View File
@@ -1,24 +1,65 @@
server { server {
listen 80; listen 80; # 88 yerine 80 kullanın
add_header Content-Security-Policy "upgrade-insecure-requests";
index index.php index.html;
server_name localhost; server_name localhost;
root /var/www/public; root /var/www/public;
index index.php index.html;
# Keep-alive ve connection ayarları (bağlantı birikmesini önlemek için)
keepalive_timeout 65;
keepalive_requests 100;
client_max_body_size 20M;
client_body_timeout 60s;
client_header_timeout 60s;
send_timeout 60s;
# HTTPS için proxy headers
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
# Güvenlik başlıkları
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
# Ana location
location / { location / {
try_files $uri $uri/ /index.php?$query_string; try_files $uri $uri/ /index.php?$query_string;
} }
# PHP dosyaları için
location ~ \.php$ { location ~ \.php$ {
proxy_set_header X-Forwarded-Proto $scheme;
include fastcgi_params;
fastcgi_pass app:9000; fastcgi_pass app:9000;
fastcgi_index index.php; fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# HTTPS için ek parametreler
fastcgi_param HTTPS on;
fastcgi_param HTTP_X_FORWARDED_PROTO https;
# Timeout ayarları
fastcgi_read_timeout 300;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 300;
# FastCGI keep-alive ve buffer ayarları (bağlantı birikmesini önlemek için)
fastcgi_keep_conn on;
fastcgi_buffering on;
fastcgi_buffer_size 4k;
fastcgi_buffers 8 4k;
fastcgi_busy_buffers_size 8k;
# Connection pool ayarları
fastcgi_max_temp_file_size 0;
} }
# Gizli dosyaları engelle
location ~ /\.ht { location ~ /\.ht {
deny all; deny all;
} }
# Log dosyalarını engelle
location ~ /\.log {
deny all;
}
} }
+7 -5
View File
@@ -1,3 +1,4 @@
@if($rate)
<div class="card"> <div class="card">
<div class="title"> <div class="title">
@@ -5,10 +6,10 @@
{{$currencyName}} {{$currencyName}}
</p> </p>
<p class="percent" style="color: {{ $rate['Change'] > 0 ? 'green' : '#B9101E' }}"> <p class="percent" style="color: {{ ($rate['Change'] ?? 0) > 0 ? 'green' : '#B9101E' }}">
{{ $rate['Change'] }}% {{ $rate['Change'] ?? 0 }}%
</p> </p>
@if($rate['Change'] > 0) @if(($rate['Change'] ?? 0) > 0)
<svg width="20" height="20" fill="green" style="position: relative; top: -2px;" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg" transform="rotate(180)"> <path d="M384 576q0-26 19-45t45-19h896q26 0 45 19t19 45-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45z"></path> </svg> <svg width="20" height="20" fill="green" style="position: relative; top: -2px;" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg" transform="rotate(180)"> <path d="M384 576q0-26 19-45t45-19h896q26 0 45 19t19 45-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45z"></path> </svg>
@else @else
<svg width="20" height="20" fill="#B9101E" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"> <path d="M384 576q0-26 19-45t45-19h896q26 0 45 19t19 45-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45z"></path> </svg> <svg width="20" height="20" fill="#B9101E" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"> <path d="M384 576q0-26 19-45t45-19h896q26 0 45 19t19 45-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45z"></path> </svg>
@@ -19,12 +20,13 @@
<div class="data"> <div class="data">
<p> <p>
{{$rate['Selling']}} {{$rate['Selling'] ?? '0.00'}}
</p> </p>
<div class="range"> <div class="range">
<div class="fill" style="background-color: {{ $rate['Change'] > 0 ? 'green' : '#B9101E' }};"> <div class="fill" style="background-color: {{ ($rate['Change'] ?? 0) > 0 ? 'green' : '#B9101E' }};">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@endif
+10 -49
View File
@@ -1,62 +1,23 @@
<!-- See https://github.com/stoplightio/elements/blob/main/docs/getting-started/elements/elements-options.md for config -->
<!doctype html> <!doctype html>
<html lang="en" class="dark"> <html>
<head> <head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Truncgil Finance</title> <title>Truncgil Finance</title>
<!-- Embed elements Elements via Web Component --> <meta charset="utf-8"/>
<script src="https://unpkg.com/@stoplight/elements@9.0.0/web-components.min.js"></script> <meta
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements@9.0.0/styles.min.css"> name="viewport"
content="width=device-width, initial-scale=1"/>
<style> <style>
body { body {
height: 100vh; margin: 0;
}
elements-api {
--elements-border-radius: 6px;
}
.sl-inline img {
width: 400px;
margin: 0 auto;
display: block;
}
.sl-prose p {
font-size: var(--fs-paragraph);
margin-bottom: 1em;
margin-top: 1em;
}
.sl-text-base {
font-size: 16px;
}
h4.sl-text-paragraph.sl-leading-snug.sl-font-prose.sl-font-semibold.sl-text-heading {
display: none;
} }
</style> </style>
</head> </head>
<body> <body>
<elements-api
apiDescriptionUrl="{{ route("scribe.openapi") }}"
router="hash"
layout="responsive"
appearance="auto"
hideTryIt=""
logo="img/logo-light.svg"
/>
<script> <script
setTimeout(function() { id="api-reference"
const linkElement = document.querySelector('a.sl-flex.sl-items-center.sl-px-4.sl-py-3.sl-border-t'); data-url="{{ route("scribe.openapi") }}">
if (linkElement) {
linkElement.href = "https://truncgil.com"; // Yeni URL'yi buraya ekleyin
linkElement.innerHTML = '<img src="https://truncgil.com.tr/yatay.svg" width="100" alt="Truncgil Teknoloji">'; // Resim URL'sini ve alternatif metni buraya ekleyin
}
}, 1000); // 1 saniye gecikme
</script> </script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body> </body>
</html> </html>
+19 -6
View File
@@ -128,24 +128,37 @@
</header> </header>
<main class="mt-6"> <main class="mt-6">
@php @php
$response = file_get_contents('https://finance.truncgil.com/api/today.json'); try {
$data = json_decode($response, true); $response = @file_get_contents('https://finance.truncgil.com/api/today.json');
$data = $response ? json_decode($response, true) : null;
} catch (\Exception $e) {
$data = null;
}
$currencies = ['USD', 'EUR', 'GBP', 'GRA', 'BTC', 'ETH', 'XRP', 'LTC']; $currencies = ['USD', 'EUR', 'GBP', 'GRA', 'BTC', 'ETH', 'XRP', 'LTC'];
$rates = []; $rates = [];
foreach ($currencies as $currency) { if (isset($data['Rates'])) {
$rates[$currency] = $data['Rates'][$currency] ?? null; foreach ($currencies as $currency) {
if (isset($data['Rates'][$currency])) {
$rates[$currency] = $data['Rates'][$currency];
}
}
} }
@endphp @endphp
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
@foreach($rates AS $currencyName => $rate) @forelse($rates AS $currencyName => $rate)
<div class="w-full md:w-auto"> <div class="w-full md:w-auto">
@include('currency', [ @include('currency', [
'currencyName' => $currencyName, 'currencyName' => $currencyName,
'rate' => $rate 'rate' => $rate
]) ])
</div> </div>
@endforeach @empty
<div class="col-span-full text-center py-10">
<p class="text-gray-500">Service temporarily unavailable. Please try again later.</p>
</div>
@endforelse
</div> </div>
Executable
+32
View File
@@ -0,0 +1,32 @@
#!/bin/bash
# Proje dizinine git
cd "$(dirname "$0")"
# Proje adını tanımlayalım
PROJECT_NAME="finance"
DB_PORT="3308"
echo "🚀 '$PROJECT_NAME' projesi kontrol ediliyor..."
# 1. Port çakışmasını kontrol et ve temizle
echo "🔍 Port $DB_PORT kontrol ediliyor..."
CONFLICTING_CONTAINER=$(docker ps -q --filter "publish=$DB_PORT")
if [ ! -z "$CONFLICTING_CONTAINER" ]; then
echo "⚠️ Port $DB_PORT, $(docker ps --filter "id=$CONFLICTING_CONTAINER" --format "{{.Names}}") tarafından kullanılıyor. Temizleniyor..."
docker rm -f "$CONFLICTING_CONTAINER"
fi
# 2. İsim çakışmalarını temizle
echo "🧹 İsim çakışmaları temizleniyor..."
docker rm -f truncgil-finance-app truncgil-finance-web truncgil-finance-db 2>/dev/null
# 3. Servisleri başlat
echo "🆙 Servisler başlatılıyor..."
docker compose -p "$PROJECT_NAME" up -d --remove-orphans
# Durumu göster
echo "📊 Mevcut durum ($PROJECT_NAME):"
docker compose -p "$PROJECT_NAME" ps
echo "✅ '$PROJECT_NAME' projesi başarıyla ayağa kaldırıldı!"