Menedżer Freelance
Masz wielu klientów, kilka projektów jednocześnie, terminy do dopilnowania i płatności do kontrolowania? Menedżer Freelance to praktyczna aplikacja stworzona z myślą o freelancerach, którzy chcą mieć wszystko w jednym miejscu.
Co zyskujesz?
Jak działa aplikacja?
Aplikacja działa bez instalacji i bez skomplikowanej konfiguracji. Wystarczy ją uruchomić w przeglądarce i od razu możesz rozpocząć pracę.
1. Dodaj klientów
Wpisz nazwę klienta oraz dane kontaktowe, aby zbudować własną bazę współprac.
2. Twórz nowe zlecenia
Dodawaj projekty, przypisuj je do klientów, ustawiaj kwotę, status realizacji oraz termin zakończenia.
3. Monitoruj postępy
Sprawdzaj, które projekty są aktywne, zakończone lub wymagają uwagi.
4. Kontroluj finanse
Aplikacja automatycznie podlicza przychody, dzięki czemu zawsze wiesz, ile zarabiasz.
5. Wszystko zapisuje się automatycznie
Dane przechowywane są w pamięci przeglądarki (Local Storage), więc po zamknięciu strony nic nie przepada.
Dlaczego warto?
Freelancerzy często korzystają z kilku narzędzi jednocześnie: notatek, arkuszy Excel, kalendarza i wiadomości e-mail. Menedżer Freelance łączy najważniejsze funkcje w jednym miejscu i oszczędza Twój czas.
Dla kogo?
- grafików
- programistów
- copywriterów
- marketerów
- fotografów
- konsultantów
- wszystkich pracujących na własny rachunek
Zacznij już dziś
Uporządkuj klientów, projekty i finanse. Skup się na pracy, a organizację zostaw aplikacji Menedżer Freelance.
Polityka Prywatności
Ochrona Twoich danych
Szanujemy Twoją prywatność i dbamy o bezpieczeństwo informacji wprowadzanych do aplikacji Menedżer Freelance.
Jak działają dane w aplikacji?
Aplikacja została zaprojektowana jako narzędzie działające lokalnie w przeglądarce internetowej. Oznacza to, że dane wpisywane przez użytkownika, takie jak:
- lista klientów
- nazwy projektów i zleceń
- terminy realizacji
- kwoty i przychody
- ustawienia aplikacji
zapisywane są wyłącznie na urządzeniu użytkownika przy użyciu technologii Local Storage przeglądarki.
Brak przesyłania danych na serwer
Aplikacja nie wysyła wprowadzonych danych do zewnętrznych serwerów, baz danych ani usług trzecich. Wszystkie informacje pozostają lokalnie na Twoim komputerze lub urządzeniu.
Pełna kontrola użytkownika
Użytkownik ma pełną kontrolę nad swoimi danymi. Może je w dowolnym momencie:
- edytować
- usuwać
- wyczyścić pamięć przeglądarki
- usunąć aplikację z urządzenia
Bezpieczeństwo
Zalecamy korzystanie z aktualnej wersji przeglądarki internetowej oraz zabezpieczenie urządzenia hasłem, aby zwiększyć poziom ochrony danych lokalnych.
Pliki cookies
Podstawowa wersja aplikacji nie wykorzystuje plików cookies do śledzenia użytkowników ani celów marketingowych.
Zmiany polityki prywatności
W przypadku rozbudowy aplikacji o nowe funkcje online (np. logowanie, synchronizacja w chmurze, kopie zapasowe), polityka prywatności może zostać zaktualizowana.
Kontakt
W razie pytań dotyczących prywatności i bezpieczeństwa danych skontaktuj się z administratorem aplikacji.
Menedżer Freelance
Klienci, projekty, terminy i płatnościKlienci
Aktywne zlecenia
Przychód
Dodaj klienta
Lista klientów
Zlecenia
| Projekt | Klient | Status | Kwota | Termin | Akcje |
|---|
Kod po stronie przeglądarki
<link type="text/css" href="http://www.dariuszrorat.ugu.pl/assets/css/bootstrap/wcag-outline.min.css" rel="stylesheet">
<div id="app" class="py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h3 class="h3 mb-0">Menedżer Freelance</h3>
<small class="text-muted">Klienci, projekty, terminy i płatności</small>
</div>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#jobModal">+ Nowe zlecenie</button>
</div>
<div class="row g-3 mb-4">
<div class="col-md-4">
<div class="card p-3">
<h4 class="h6">Klienci</h4>
<div id="clientsCount" class="display-6">0</div>
</div>
</div>
<div class="col-md-4">
<div class="card p-3">
<h4 class="h6">Aktywne zlecenia</h4>
<div id="activeCount" class="display-6">0</div>
</div>
</div>
<div class="col-md-4">
<div class="card p-3">
<h4 class="h6">Przychód</h4>
<div id="income" class="display-6">0 zł</div>
</div>
</div>
</div>
<div class="row g-4">
<div class="col-lg-4">
<div class="card p-3">
<h4 class="h5">Dodaj klienta</h4>
<input id="clientName" class="form-control mb-2" placeholder="Nazwa klienta" aria-label="Nazwa klienta">
<input id="clientEmail" class="form-control mb-2" placeholder="Email" aria-label="Email">
<button class="btn btn-success w-100" onclick="addClient()">Dodaj</button>
</div>
<div class="card p-3 mt-3">
<h4 class="h5">Lista klientów</h4>
<ul id="clientsList" class="list-group list-group-flush"></ul>
</div>
</div>
<div class="col-lg-8">
<div class="card p-3">
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 class="h5 mb-0">Zlecenia</h4>
<input id="search" class="form-control w-auto" placeholder="Szukaj..." aria-label="Szukaj" oninput="renderJobs()">
</div>
<div class="table-responsive">
<table class="table align-middle">
<thead>
<tr>
<th>Projekt</th>
<th>Klient</th>
<th>Status</th>
<th>Kwota</th>
<th>Termin</th>
<th>Akcje</th>
</tr>
</thead>
<tbody id="jobsTable"></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="jobModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="h5 modal-title">Nowe zlecenie</h4>
<button class="btn-close" data-bs-dismiss="modal" aria-label="Zamknij"></button>
</div>
<div class="modal-body">
<input id="jobTitle" class="form-control mb-2" placeholder="Nazwa projektu" aria-label="Nazwa projektu">
<select id="jobClient" class="form-select mb-2" aria-label="Klient"></select>
<select id="jobStatus" class="form-select mb-2" aria-label="Status">
<option>Nowe</option>
<option>W trakcie</option>
<option>Zakończone</option>
</select>
<input id="jobAmount" type="number" class="form-control mb-2" placeholder="Kwota" aria-label="Kwota">
<input id="jobDeadline" type="date" class="form-control mb-2" aria-label="Deadline">
</div>
<div class="modal-footer"><button class="btn btn-primary" onclick="addJob()">Zapisz</button></div>
</div>
</div>
</div>
<script>
let clients = JSON.parse(localStorage.getItem('fm_clients') || '[]');
let jobs = JSON.parse(localStorage.getItem('fm_jobs') || '[]');
function save() {
localStorage.setItem('fm_clients', JSON.stringify(clients));
localStorage.setItem('fm_jobs', JSON.stringify(jobs));
}
function addClient() {
const name = document.getElementById('clientName').value.trim();
const email = document.getElementById('clientEmail').value.trim();
if (!name) return;
clients.push({
id: Date.now(),
name,
email
});
document.getElementById('clientName').value = '';
document.getElementById('clientEmail').value = '';
refresh();
}
function addJob() {
const title = jobTitle.value.trim();
if (!title) return;
jobs.push({
id: Date.now(),
title,
clientId: +jobClient.value,
status: jobStatus.value,
amount: +jobAmount.value || 0,
deadline: jobDeadline.value
});
bootstrap.Modal.getInstance(document.getElementById('jobModal')).hide();
jobTitle.value = '';
jobAmount.value = '';
jobDeadline.value = '';
refresh();
}
function deleteJob(id) {
jobs = jobs.filter(j => j.id !== id);
refresh();
}
function renderClients() {
clientsList.innerHTML = '';
jobClient.innerHTML = '';
clients.forEach(c => {
clientsList.innerHTML += `<li class="list-group-item d-flex justify-content-between"><span>${c.name}</span><small>${c.email||''}</small></li>`;
jobClient.innerHTML += `<option value="${c.id}">${c.name}</option>`;
});
}
function badge(status) {
return status === 'Zakończone' ? 'success' : status === 'W trakcie' ? 'warning text-dark' : 'secondary';
}
function renderJobs() {
const q = search.value.toLowerCase();
jobsTable.innerHTML = '';
jobs.filter(j => j.title.toLowerCase().includes(q)).forEach(j => {
const c = clients.find(x => x.id === j.clientId) || {
name: '-'
};
jobsTable.innerHTML += `<tr><td>${j.title}</td><td>${c.name}</td><td><span class="badge bg-${badge(j.status)}">${j.status}</span></td><td>${j.amount} zł</td><td>${j.deadline||'-'}</td><td><button class="btn btn-sm btn-outline-danger" onclick="deleteJob(${j.id})">Usuń</button></td></tr>`;
});
}
function stats() {
clientsCount.textContent = clients.length;
activeCount.textContent = jobs.filter(j => j.status !== 'Zakończone').length;
income.textContent = jobs.reduce((a, b) => a + b.amount, 0) + ' zł';
}
function refresh() {
save();
renderClients();
renderJobs();
stats();
}
refresh();
</script>
Kod po stronie serwera
Brak kodu serwera
Ta aplikacja działa wyłącznie w przeglądarce i nie korzysta z kodu po stronie serwera.
Licencja
## BSD-3-Clause License Agreement
BSD-3-Clause
Сopyright (c) 2026 Dariusz Rorat
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Kategorie
Technologie
Masz pomysł na podobną aplikację?
Chętnie pomogę zaplanować MVP, funkcjonalności oraz dalszy rozwój produktu.
Omówmy Twój pomysł