1+ <!DOCTYPE html>
2+ < html >
3+ < head >
4+ < title > Habit Tracker</ title >
5+ < style >
6+ body {
7+ font-family : sans-serif;
8+ }
9+
10+ table {
11+ border-collapse : collapse;
12+ width : 80% ; /* Adjust as needed */
13+ margin : 20px auto; /* Center the table */
14+ }
15+
16+ th , td {
17+ border : 1px solid # ddd ;
18+ padding : 8px ;
19+ text-align : center;
20+ }
21+
22+ th {
23+ background-color : # f2f2f2 ;
24+ }
25+
26+ td : not (: first-child ) { /* Style all cells except the first column */
27+ cursor : pointer; /* Make cells interactive */
28+ }
29+
30+ td .completed {
31+ background-color : # 4CAF50 ; /* Green for completed */
32+ color : white;
33+ }
34+
35+ .add-habit-container {
36+ margin : 20px auto;
37+ width : 80% ;
38+ display : flex;
39+ align-items : center;
40+ }
41+
42+ # newHabitInput {
43+ flex-grow : 1 ; /* Input takes up remaining space */
44+ padding : 8px ;
45+ margin-right : 10px ;
46+ }
47+
48+ # addHabitBtn {
49+ padding : 8px 12px ;
50+ background-color : # 007bff ;
51+ color : white;
52+ border : none;
53+ cursor : pointer;
54+ }
55+ .delete-button {
56+ background-color : # ff6347 ;
57+ color : white;
58+ border : none;
59+ padding : 2px 6px ;
60+ cursor : pointer;
61+ border-radius : 4px ;
62+ margin-left : 5px ; /* Space it out from the habit text*/
63+ }
64+
65+ </ style >
66+ </ head >
67+ < body >
68+
69+ < h1 > Habit Tracker</ h1 >
70+
71+ < div class ="add-habit-container ">
72+ < input type ="text " id ="newHabitInput " placeholder ="Enter a new habit ">
73+ < button id ="addHabitBtn "> Add Habit</ button >
74+ </ div >
75+
76+ < table id ="habitTable ">
77+ < thead >
78+ < tr >
79+ < th > Habit</ th >
80+ < th > Monday</ th >
81+ < th > Tuesday</ th >
82+ < th > Wednesday</ th >
83+ < th > Thursday</ th >
84+ < th > Friday</ th >
85+ < th > Saturday</ th >
86+ < th > Sunday</ th >
87+ </ tr >
88+ </ thead >
89+ < tbody >
90+ </ tbody >
91+ </ table >
92+
93+ < script >
94+ const habitTable = document . getElementById ( 'habitTable' ) ;
95+ const newHabitInput = document . getElementById ( 'newHabitInput' ) ;
96+ const addHabitBtn = document . getElementById ( 'addHabitBtn' ) ;
97+
98+ // Function to add a new habit row
99+ function addHabitRow ( habitText ) {
100+ const newRow = habitTable . insertRow ( ) ;
101+ const habitCell = newRow . insertCell ( ) ;
102+ habitCell . textContent = habitText ;
103+
104+ // Add a delete button to the habit cell
105+ const deleteButton = document . createElement ( 'button' ) ;
106+ deleteButton . textContent = "X" ;
107+ deleteButton . className = "delete-button" ;
108+ deleteButton . addEventListener ( 'click' , ( ) => {
109+ newRow . remove ( ) ; // Remove the entire row when the button is clicked
110+ saveHabits ( ) ; // Save habits after deletion
111+ } ) ;
112+ habitCell . appendChild ( deleteButton ) ;
113+
114+
115+
116+ // Create day cells and add event listeners
117+ for ( let i = 0 ; i < 7 ; i ++ ) {
118+ const dayCell = newRow . insertCell ( ) ;
119+ dayCell . addEventListener ( 'click' , toggleHabitCompletion ) ;
120+ }
121+ saveHabits ( ) ;
122+ }
123+
124+ // Function to toggle habit completion status
125+ function toggleHabitCompletion ( ) {
126+ this . classList . toggle ( 'completed' ) ;
127+ saveHabits ( ) ;
128+ }
129+
130+ // Event listener for adding habits
131+ addHabitBtn . addEventListener ( 'click' , ( ) => {
132+ const habitText = newHabitInput . value . trim ( ) ;
133+ if ( habitText ) {
134+ addHabitRow ( habitText ) ;
135+ newHabitInput . value = '' ; // Clear input
136+ } else {
137+ alert ( "Please Enter a Habit" ) ;
138+ }
139+ } ) ;
140+
141+ //Pressing enter in input adds habit.
142+ newHabitInput . addEventListener ( 'keypress' , function ( e ) {
143+ if ( e . key === 'Enter' ) {
144+ const habitText = newHabitInput . value . trim ( ) ;
145+ if ( habitText ) {
146+ addHabitRow ( habitText ) ;
147+ newHabitInput . value = '' ; // Clear input
148+ } else {
149+ alert ( "Please Enter a Habit" ) ;
150+ }
151+ }
152+ } ) ;
153+
154+
155+
156+ // --- Local Storage Functions ---
157+
158+ function saveHabits ( ) {
159+ const habitData = [ ] ;
160+ const rows = habitTable . querySelectorAll ( 'tbody tr' ) ;
161+
162+ rows . forEach ( row => {
163+ const habitText = row . cells [ 0 ] . childNodes [ 0 ] . textContent ; //get first node of first cell to obtain habit name.
164+ const completionStatus = [ ] ;
165+ for ( let i = 1 ; i < row . cells . length ; i ++ ) {
166+ completionStatus . push ( row . cells [ i ] . classList . contains ( 'completed' ) ) ;
167+ }
168+ habitData . push ( { text : habitText , completed : completionStatus } ) ;
169+ } ) ;
170+
171+ localStorage . setItem ( 'habits' , JSON . stringify ( habitData ) ) ;
172+ }
173+
174+
175+
176+ function loadHabits ( ) {
177+ const savedHabits = localStorage . getItem ( 'habits' ) ;
178+ if ( savedHabits ) {
179+ const habitData = JSON . parse ( savedHabits ) ;
180+ habitData . forEach ( habit => {
181+ const newRow = habitTable . insertRow ( ) ;
182+ const habitCell = newRow . insertCell ( ) ;
183+ habitCell . textContent = habit . text ;
184+
185+ //add delete button on load
186+ const deleteButton = document . createElement ( 'button' ) ;
187+ deleteButton . textContent = "X" ;
188+ deleteButton . className = "delete-button" ;
189+ deleteButton . addEventListener ( 'click' , ( ) => {
190+ newRow . remove ( ) ;
191+ saveHabits ( ) ;
192+ } ) ;
193+ habitCell . appendChild ( deleteButton ) ;
194+
195+
196+ for ( let i = 0 ; i < 7 ; i ++ ) {
197+ const dayCell = newRow . insertCell ( ) ;
198+ if ( habit . completed [ i ] ) {
199+ dayCell . classList . add ( 'completed' ) ;
200+ }
201+ dayCell . addEventListener ( 'click' , toggleHabitCompletion ) ;
202+ }
203+ } ) ;
204+ }
205+ }
206+
207+ // Load saved habits on page load
208+ loadHabits ( ) ;
209+ </ script >
210+
211+ </ body >
212+ </ html >
0 commit comments