Visuele planning maken

Status
Niet open voor verdere reacties.

Joete

Gebruiker
Lid geworden
19 sep 2008
Berichten
87
Hey allemaal.

Ik heb de wens om een personeelsplanning die nu in Excel zit om te zetten naar een website. De Excel is namelijk erg traag aan het worden en moet uit zoveel delen data halen dat dit langzaamaan onwerkbaar wordt (qua traagheid voor collega, maar ook code-technisch voor mij).

De website moet een soort header/menu krijgen, met daaronder een groot vak voor de planning. Dit lukt nog prima.
Het grote deel van de planning loop ik echter helemaal in vast, ondertussen al zoveel pogingen gedaan dat ik ff niet meer weet wat nu wel en niet meer werkt :D

  • De planning moet (in het grote planningvak) linksboven een vlak hebben wat altijd blijft staan
  • Rechts daarvan een reeks met jaren, maanden en weken (lukt) wat bij verticaal scrollen blijft staan, maar bij horizontaal scrollen wel mee schuift
  • Links onder het vaste blok moet een kolom staan met projecten en namen (lukt) die bij verticaal scrollen mee schuift, maar bij horizontaal scrollen blijft staan
  • Dan het vak rechtsonder met de planningsgegevens (vullen gaat goed komen) wat in beide richtingen scrollen meeschuift

Code:
VAST BLOK             |   Jaren (vast bovenaan)
VAST BLOK             |   Maanden
VAST BLOK             |   Weken
______________________|___________________
                      |
Project (vast links)  |   planning (scrollend in beide richtingen)
Medewerker            |   planning
Medewerker            |   planning
Project               |   planning
Medewerker            |   planning
Medewerker            |   planning
Medewerker            |   planning
Enz..

Pogingen die ik gedaan heb:
  • Met DIVs, maar dan kreeg ik of de jaren, maanden, weken niet vast/scrollend/sticky, of de projecten en medewerkers niet
  • Met Tabellen, met behulp van sticky, maar dan kon ik geen tekst over het randje van de cel laten lopen en scrollen de borders over de sticky rijen heen
  • Nog meer pogingen met DIVs, maar daar ben ik ondertussen de weg helemaal kwijt

Kan iemand mij op weg helpen met de tags die ik in mijn CSS moet gebruiken? Position, Display, Overflow, wanneer wel en niet Top/Left, wanneer wel en niet margin-left/-top. Ik volg mezelf ff niet meer in mijn bestanden :eek:
Het is de bedoeling dat het een balkenplanning wordt die breder is dan het scherm en afhankelijk van het aantal projecten en medewerkers er geladen worden ook hoger dan het scherm.
De gegevens worden tzt uit een database gehaald en rijen zullen dan horizontaal gevuld worden. Dus projectnaam -> planning -> Medewerker 1 - > planning -> Medewerker 2 -> planning -> enz.. Vaste vakken maken is dus volgens mij geen optie, maar dat kan ook aan mijn beperkte snapvermogen liggen rondom HTML, CSS en PHP.
 
Laat eens een beginnetje zien wat je geprobeerd hebt?
Misschien was je al goed op weg?
 
Het zou inderdaad al helpen als beknd is wat er tot nu toe gemaakt is.

Maar zo te horen ben je de lay-out aan het uitvinden, zou Bootstrap met het grid systeem dan geen idee zijn of heb je dat al?
 
Data (overzichten) kunnen prima in een tabel. De layout van de pagina uiteraard niet.
Ik begrijp dat je veel functionaliteit al hebt.

Met deze class'es kan je de overflow van de tabel verbergen of scrollable maken (zie voorbeeld in zip)

overflow-scroll , overflow-hidden , overflow-auto
overflow-x-scroll , overflow-x-hidden , overflow-x-auto
overflow-y-scroll , overflow-y-hidden , overflow-y-auto
 

Bijlagen

  • planner-layout.zip
    5,1 KB · Weergaven: 23
Laatst bewerkt:
Sorry, duurde helaas iets langer voor ik weer achter mijn eigen laptopje kon.

Laat eens een beginnetje zien wat je geprobeerd hebt?
Misschien was je al goed op weg?
Die vraag was ik al bang voor :eek: Het is veel verschillende code en doe veel met include en verschillende css-en. Ik zal hieronder een samenvatting proberen te maken.

Het zou inderdaad al helpen als beknd is wat er tot nu toe gemaakt is.

Maar zo te horen ben je de lay-out aan het uitvinden, zou Bootstrap met het grid systeem dan geen idee zijn of heb je dat al?
Bootstrap ken ik niet...zal ik eens naar zoeken. Voor tot nu toe gemaakte, zie hieronder.

Data (overzichten) kunnen prima in een tabel. De layout van de pagina uiteraard niet.
Ik begrijp dat je veel functionaliteit al hebt.

Met deze class'es kan je de overflow van de tabel verbergen of scrollable maken (zie voorbeeld in zip)

overflow-scroll , overflow-hidden , overflow-auto
overflow-x-scroll , overflow-x-hidden , overflow-x-auto
overflow-y-scroll , overflow-y-hidden , overflow-y-auto
Thnx. Net gedownload, zo ff op mijn NAS gooien om het te bekijken :thumb:

Wat ik tot nu toe geprobeerd heb:
TABELLEN:
php:
Code:
<?php
if (date("w") == 0) {
	$date = new DateTime('now'); // Huidige datum -> zondag
} else {
	$date = new DateTime('now'); // Huidige datum -> geen zondag
	$date->sub(new DateInterval('P' . date("w") . 'D')); // -> terug naar de laatste zondag
}			
$date->sub(new DateInterval('P1M')); // Begin 1 maand eerder met de planning
$vandaag = new DateTime('now');
$aantalweken = 150 * 5;
?>

<table>
	<thead>
	<!-- KOLOMKOPPEN -->
		<!-- JAARTAL -->
		<tr class='jaar'>
			<?php
			$jdate = new DateTime($date->format("Y-M-d"));
			$jdate2 = new DateTime($date->format("Y-M-d"));
			$jdate2->sub(new DateInterval('P1D'));
			echo "<th class='jaar titel rechts jaar_leeg'>Jaar</th>";
			for ($j = 1; $j <= $aantalweken; $j++) {
				if (($jdate->format("w") > 0) AND ($jdate->format("w") < 7)) {
					if (($j == 1) OR ($jdate->format("Y") <> $jdate2->format("Y"))) {
						echo "<th class='jaar plan links'>" . $jdate->format("Y") . "</th>";
					} else {
						echo "<th class='jaar plan jaar_leeg'></th>";
					}
				}
				$jdate->add(new DateInterval('P1D'));
				$jdate2->add(new DateInterval('P1D'));
			}
			?>
		</tr>
		<!-- MAAND AFK -->
		<tr class='maand'>
			<?php
			$mdate = new DateTime($date->format("Y-M-d"));
			$mdate2 = new DateTime($date->format("Y-M-d"));
			$mdate2->sub(new DateInterval('P1D'));
			echo "<th class='maand titel rechts maand_leeg'>Maand</th>";
			for ($m = 1; $m <= $aantalweken; $m++) {
				if (($mdate->format("w") > 0) AND ($mdate->format("w") < 7)) {
					if (($m == 1) OR ($mdate->format("M") <> $mdate2->format("M"))) {
						echo "<th class='maand plan links'>" . $mdate->format("M") . "</th>";
					} else {
						echo "<th class='maand plan maand_leeg'></th>";
					}
				}
				$mdate->add(new DateInterval('P1D'));
				$mdate2->add(new DateInterval('P1D'));
			}
			?>
		</tr>
		<!-- WEEKNUMMER -->
		<tr class='week'>
			<?php
			$wdate = new DateTime($date->format("Y-M-d"));
			echo "<th class='week titel rechts week_leeg'>Week</th>";
			for ($w = 1; $w <= $aantalweken; $w++) {
				if ($wdate->format("w") == 3) {
					echo "<th class='week plan midden'>" . $wdate->format("W") . "</th>";
				} else {
					echo "<th class='week plan midden'></th>";
				}
				$wdate->add(new DateInterval('P1D'));
			}
			?>
		</tr>
	</thead>
	
	<tbody>
	<!-- PLANNING -->
		<?php
		for ($p = 1; $p <= 10; $p++) {
			echo "<tr class='blanco'>";
				echo "<th class='blanco titel'>&nbsp;</th>";
				$bldate = new DateTime($date->format("Y-M-d"));
				$bldate2 = new DateTime($date->format("Y-M-d"));
				$bldate2->add(new DateInterval('P1D'));
				for ($b = 1; $b <= $aantalweken; $b++) {
					if (($bldate <= $vandaag) AND ($bldate2 >= $vandaag)) {
						$planlijn = planlijn();
					} else {
						$planlijn = "";
					}
					echo "<td class='blanco plan midden " . $planlijn . "'>&nbsp;</td>";
					$bldate->add(new DateInterval('P1D'));
					$bldate2->add(new DateInterval('P1D'));
				}
			echo "</tr'>";
			echo "<tr class='project'>";
				echo "<th class='project titel links'>Projectnaam " . $p . "</th>";
				$pdate = new DateTime($date->format("Y-M-d"));
				$pdate2 = new DateTime($date->format("Y-M-d"));
				$pdate2->add(new DateInterval('P1D'));
				for ($i = 1; $i <= $aantalweken; $i++) {
					if (($pdate <= $vandaag) AND ($pdate2 >= $vandaag)) {
						$planlijn = planlijn();
					} else {
						$planlijn = "";
					}
					echo "<td class='project plan midden " . $planlijn . "'>" . $i . "</td>";
					$pdate->add(new DateInterval('P1D'));
					$pdate2->add(new DateInterval('P1D'));
				}
			echo "</tr>";
			for ($j = 1; $j <= 6; $j++) {
				echo "<tr class='medewerker'>";
					echo "<th class='medewerker titel links inspringen'>Medewerker " . $j . "</th>";
					$pdate = new DateTime($date->format("Y-M-d"));
					$pdate2 = new DateTime($date->format("Y-M-d"));
					$pdate2->add(new DateInterval('P1D'));
					for ($i = 1; $i <= $aantalweken; $i++) {
						if (($pdate <= $vandaag) AND ($pdate2 >= $vandaag)) {
							$planlijn = planlijn();
						} else {
							$planlijn = "";
						}
						echo "<td class='medewerker plan midden " . $planlijn . "'>&nbsp;</td>";
						$pdate->add(new DateInterval('P1D'));
						$pdate2->add(new DateInterval('P1D'));
					}
				echo "</tr>";
			}
		}
		?>
	</tbody>
</table>
css:
Code:
/* ALGEMEEN TABEL */
table {
	position: relative;
	border-collapse: collapse;
	table-layout: fixed;
	width: 4800px;
}

/* KOLOMKOPPEN */
thead tr:nth-child(1) th {
	position: -webkit-sticky;
	position: sticky;
	top: 0px;
	height: 14px;
	background-color: var(--MB_blauw);
	color: #FFFFFF;
	border-left: 1px solid var(--MB_geel);
	z-index: 5;
}

thead tr:nth-child(2) th {
	position: -webkit-sticky;
	position: sticky;
	top: 20px;	
	height: 14px;
	background-color: var(--MB_blauw);
	color: #FFFFFF;
	border-left: 1px solid var(--MB_geel);
	z-index: 5;
}

thead tr:nth-child(3) th {
	position: -webkit-sticky;
	position: sticky;
	top: 40px;	
	height: 14px;
	background-color: var(--MB_geel);
	color: var(--MB_blauw);
	border-left: 1px solid var(--MB_blauw);
	z-index: 5;
}

thead tr th:first-child {
	left: 0px;
	z-index: 8;
}

/* RIJEN */
tbody th {
	position: -webkit-sticky;
	position: sticky;
	left: 0px;
	z-index: 3;
}

tr.blanco, th.blanco, td.blanco {
	height: 8px;
	background-color: #FFFFFF;
}

tr.project, th.project, td.project {
	height: 16px;
	font-size: 14pt;
	background-color: #FFFFFF;
	color: var(--MB_blauw);
	font-weight: bold;
	border-bottom: 1px solid #CCCCCC;
}

tr.medewerker, th.medewerker, td.medewerker {
	height: 12px;
	background-color: #FFFFFF;
	color: var(--MB_lichtblauw);
}

/* CELLEN */
td.titel, th.titel {
	width: 300px;
	background-image: linear-gradient(
		to left, 
		rgba(80, 80, 80, 0.3), 
		rgba(80, 80, 80, 0.3) 1%, 
		rgba(80, 80, 80, 0) 1%, 
		rgba(80, 80, 80, 0) 100%
	);
}

td.plan, th.plan {
	width: 6px !important;
	overflow: visible;
	/*width: 30px !important;*/
}

td.plan {
	border-left: 1px solid #CCCCCC;
	z-index: -1;
}

th.jaar_leeg, th.maand_leeg {
	border-left: 1px solid var(--MB_blauw) !important;
}

th.week_leeg {
	border-left: 1px solid var(--MB_geel) !important;
}

/* OVERIGE */ 
.links {
	text-align: left;
}

.midden {
	text-align: center;
}

.rechts {
	text-align: right;
	padding-right: 5px;
}

.inspringen {
	padding-left: 15px;
}

DIVS:
php:
Code:
<!-- START MAIN PLANNING -->
<div class='planning_main'>
	<?php
	if (date("w") == 0) {
		$date = new DateTime('now'); // Huidige datum
	} else {
		$date = new DateTime('now'); // Huidige datum
		$date->sub(new DateInterval('P' . date("w") . 'D'));
	}			
	$date->sub(new DateInterval('P1M')); // Begin 1 maand eerder met de planning
	$vandaag = new DateTime('now');
	
	// Jaren
	echo "<div class='rij rijjaar'>";
		$jdate = new DateTime($date->format("Y-M-d"));
		$jdate2 = new DateTime($date->format("Y-M-d"));
		$jdate2->sub(new DateInterval('P7D'));
		echo "<div class='medewerker lijst jaar rechts'>Jaar</div>";
		for ($j = 1; $j <= 150; $j++) {
			if (($j == 1) OR ($jdate->format("Y") <> $jdate2->format("Y"))) {
				echo "<div class='medewerker planningcel jaar links'>" . $jdate->format("Y") . "</div>";
			} else {
				echo "<div class='medewerker planningcel jaar leeg'>&nbsp;</div>";
			}
			$jdate->add(new DateInterval('P7D'));
			$jdate2->add(new DateInterval('P7D'));
		}
	echo "</div>";
	// Maanden
	echo "<div class='rij rijmaand'>";
		$mdate = new DateTime($date->format("Y-M-d"));
		$mdate2 = new DateTime($date->format("Y-M-d"));
		$mdate2->sub(new DateInterval('P7D'));
		echo "<div class='medewerker lijst maand rechts'>Maand</div>";
		for ($m = 1; $m <= 150; $m++) {
			if (($m == 1) OR ($mdate->format("M") <> $mdate2->format("M"))) {
				echo "<div class='medewerker planningcel maand links'>" . $mdate->format("M") . "</div>";
			} else {
				echo "<div class='medewerker planningcel maand leeg'>&nbsp;</div>";
			}
			$mdate->add(new DateInterval('P7D'));
			$mdate2->add(new DateInterval('P7D'));
		}
	echo "</div>";
	// Weken
	echo "<div class='rij rijweek'>";
		$wdate = new DateTime($date->format("Y-M-d"));
		echo "<div class='medewerker lijst week rechts'>Week</div>";
		for ($w = 1; $w <= 150; $w++) {
			echo "<div class='medewerker planningcel week'>" . $wdate->format("W") . "</div>";
			$wdate->add(new DateInterval('P7D'));
		}
	echo "</div>";
	// Projecten
	for ($p = 1; $p <= 10; $p++) {
		echo "<div class='titelrij'>";
			echo "<div class='project'>Projectnaam " . $p . "</div>";
			$pdate = new DateTime($date->format("Y-M-d"));
			$pdate2 = new DateTime($date->format("Y-M-d"));
			$pdate2->sub(new DateInterval('P7D'));
			for ($i = 1; $i <= 150; $i++) {
				if (($pdate >= $vandaag) AND ($pdate2 <= $vandaag)) {
					if (date("w") == "1") {
						$planlijn = "planlijn1";
					}
					elseif (date("w") == "2") {
						$planlijn = "planlijn2";
					}
					elseif (date("w") == "3") {
						$planlijn = "planlijn3";
					}
					elseif (date("w") == "4") {
						$planlijn = "planlijn4";
					}
					elseif (date("w") == "5") {
						$planlijn = "planlijn5";
					}
				} else {
					$planlijn = "";
				}
				echo "<div class='project planningcel " . $planlijn . "'>" . $i . "</div>";
				$pdate->add(new DateInterval('P7D'));
				$pdate2->add(new DateInterval('P7D'));
			}
		echo "</div>";
		for ($j = 1; $j <= 6; $j++) {
			echo "<div class='rij'>";
				echo "<div class='medewerker lijst'>Medewerker " . $j . "</div>";
				$pdate = new DateTime($date->format("Y-M-d"));
				$pdate2 = new DateTime($date->format("Y-M-d"));
				$pdate2->sub(new DateInterval('P7D'));
				for ($i = 1; $i <= 150; $i++) {
					if (($pdate >= $vandaag) AND ($pdate2 <= $vandaag)) {
						if (date("w") == "1") {
							$planlijn = "planlijn1";
						}
						elseif (date("w") == "2") {
							$planlijn = "planlijn2";
						}
						elseif (date("w") == "3") {
							$planlijn = "planlijn3";
						}
						elseif (date("w") == "4") {
							$planlijn = "planlijn4";
						}
						elseif (date("w") == "5") {
							$planlijn = "planlijn5";
						}
					} else {
						$planlijn = "";
					}
					echo "<div class='medewerker planningcel " . $planlijn . "'>&nbsp;</div>";
					$pdate->add(new DateInterval('P7D'));
					$pdate2->add(new DateInterval('P7D'));
				}
			echo "</div>";
		}
	}
	?>
</div>
css:
Code:
body {
	font-family: Calibri;
	font-size: 11pt;
	color: #324298;
	background-color: #FFFFFF;
	padding: 0px;
	margin: 0px;
	overflow-y: auto;
	overflow-x: hidden;
}

div.header {
	width: 100%;
	height: 150px;
	background-color: #FFFFFF;
	border-bottom: solid #324298 5px;
	padding: 5px;
	overflow: hidden;
	position: fixed;
	top: 0px;
	left: 0px;
	z-index: 9;
}

div.planning_main {
	width: calc(100vw-310);
	overflow-x: scroll;
	margin-left: 304px;
	margin-top: 231px;
	overflow-y: hidden;
	padding: 0px;
}

div.rijjaar {
	position: fixed;
	top: 165px;
	z-index: 9;
}

div.rijmaand {
	position: fixed;
	top: 187px;
	z-index: 9;
}

div.rijweek {
	position: fixed;
	top: 209px;
	z-index: 9;
}

div.jaar {
	background-color: #324298 !important;
	color: #FFFFFF !important;
	border-left: 1px solid #FFFFFF;
}

div.maand {
	background-color: #324298 !important;
	color: #FFFFFF !important;
	border-left: 1px solid #FFFFFF;
}

div.week {
	background-color: #F0D53E !important;
	color: #324298 !important;
	border-left: 1px solid #324298 !important;
}

div.titelrij {
	background-color: none;
	margin-top: 15px;
	white-space: nowrap;
}

div.rij {
	background-color: none;
	white-space: nowrap;
}

div.project {
	padding: 2px;
	font-size: 16pt;
	font-weight: bold;
	border-bottom: 2px solid #324298;
	position: absolute;
	width: 300px;
	left: 0px;
	color: #324298;
	text-align: left;
}

div.medewerker {
	padding: 2px;
	position: absolute;
	left: 0px;
	top: auto;
	color: #324298;
}

div.lijst {
	padding-left: 25px;
	width: 302px;
	left: 0px;
	top: auto;
	color: #324298;
	text-align: left;
	border: none !important;
}

div.planningcel {
	color: #324298;
	width: 30px !important;
	position: relative;
	display: inline-block !important;
	text-align: center;
	border-left: 1px solid #CCCCCC;
}

.rechts {
	text-align: right !important;
	padding-left: 0px !important;
}

.links {
	text-align: left !important;
}

.leeg {
	border-left: 1px solid #324298 !important;
}

In de DIV's had ik hem nog in een planning per week staan, maar dat moet straks een planning per dag worden, met visuele vakken per week (dus om de 5 dagen ga ik een border aan de zijkant plaatsen). Op die manier kan ik iets makkelijker werken met vrije dagen en een planlijn. Ik had nu voor de planlijn al 5 css opmaken, vrije dagen al 5 voor 1 dag, 1 voor een week, nog een aantal voor 2 aan een gesloten dagen en dan zou ik alle uitzonderingen nog moeten...met een schema per dag ga ik dat in ieder geval voorkomen.
Ik vul de planning zelf nu nog niet (wordt straks database verhaal) en de kolommen en de rijen gaan nu puur om wat willekeurige data, bedoeling dat dit straks ook een databases gaat komen.
Sommige onderdelen zijn nu niet helemaal lekker gecodeerd, dat ben ik ondertussen aan het oplossen met onder andere functies voor onderdelen die vaker terugkomen in de code.
Hoop dat jullie er een touw aan vast kunnen knopen...

*Edit*
Dit is een beetje het idee, maar dan andere layout en functies, maar het principe van de planning, regels, tijd en scrollen is gelijk met wat ik graag wil bereiken. Ik wil het dan gaan inzetten voor projecten, met daaronder de medewerkers, maar ook voor de medewerkers zelf dat er een overzicht ontstaat met de projecten waarbij ze ingedeeld zijn. Maar ook nog weer een deel wat afgeschermd is waarbij men alleen de projecten ziet, maar niet wie er bij betrokken zijn. Maar goed, dat heeft allemaal te maken met rechten, dat komt tzt wel. Eerst maar eens zorgen dat ik het principe van de planning onder de knie krijg.
Tom's Planner
 
Laatst bewerkt:
Het is geen 123'tje om een planner te maken die je in gedachten hebt.
Om de functionaliteit van een pro planner (zoals Toms Planner) te maken is veel kennis en tijd nodig.
Met de grote hoeveelheid code die je geeft kunnen de helpers op het forum helaas niet veel.
 
Het is ook zeker niet de bedoeling om Tom's Planner na te maken! Die functionaliteiten gaan ook veel te ver voor mijn doel. Het gaat me vooral om het grid: Datumrijen die horizontaal meescrollen, taakkolommen die verticaal meescrollen. De invulling red ik me wel mee en hoe dat ingevuld wordt ga ik op een eenvoudige manier doen.

De code werd om gevraagd...ik kan nog eens kijken of ik dat kan vereenvoudigen, misschien door de php code er uit halen en dit in te zetten naar de nuttige html. Ga ik vanavond nog eens even naar kijken.
 
Misschien is het handig om eerst een statische mock-up in HTML, JS en CSS te maken.
En als deze bevalt pas verder in te vullen met je echte data die je via PHP binnenhaalt.
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan