From f677973feb96412a780c31b5bc2f7e500b109dff Mon Sep 17 00:00:00 2001 From: tsb Date: Wed, 18 Dec 2024 11:28:35 -1000 Subject: [PATCH] initial commit --- baby_tracker/__init__.py | 0 .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 170 bytes .../__pycache__/settings.cpython-313.pyc | Bin 0 -> 2652 bytes baby_tracker/__pycache__/urls.cpython-313.pyc | Bin 0 -> 1116 bytes baby_tracker/__pycache__/wsgi.cpython-313.pyc | Bin 0 -> 668 bytes baby_tracker/asgi.py | 16 ++ baby_tracker/settings.py | 128 ++++++++++++ baby_tracker/urls.py | 23 +++ baby_tracker/wsgi.py | 16 ++ db.sqlite3 | Bin 0 -> 143360 bytes main/__init__.py | 0 main/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 162 bytes main/__pycache__/admin.cpython-313.pyc | Bin 0 -> 1072 bytes main/__pycache__/apps.cpython-313.pyc | Bin 0 -> 522 bytes main/__pycache__/forms.cpython-313.pyc | Bin 0 -> 1894 bytes main/__pycache__/models.cpython-313.pyc | Bin 0 -> 1968 bytes main/__pycache__/urls.cpython-313.pyc | Bin 0 -> 1446 bytes main/__pycache__/views.cpython-313.pyc | Bin 0 -> 8596 bytes main/admin.py | 23 +++ main/apps.py | 6 + main/forms.py | 37 ++++ main/migrations/0001_initial.py | 34 ++++ main/migrations/0002_alter_feeding_amount.py | 18 ++ ...r_feeding_amount_alter_feeding_duration.py | 23 +++ main/migrations/__init__.py | 0 .../__pycache__/0001_initial.cpython-313.pyc | Bin 0 -> 1715 bytes .../0002_alter_feeding_amount.cpython-313.pyc | Bin 0 -> 790 bytes ...unt_alter_feeding_duration.cpython-313.pyc | Bin 0 -> 950 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 173 bytes main/models.py | 34 ++++ main/templates/main/base.html | 36 ++++ main/templates/main/index.html | 5 + main/templates/main/partials/add_feed.html | 40 ++++ main/templates/main/partials/add_potty.html | 13 ++ .../main/partials/edit_feed_row.html | 37 ++++ .../main/partials/edit_potty_row.html | 35 ++++ main/templates/main/partials/feed_row.html | 30 +++ .../templates/main/partials/feed_section.html | 58 ++++++ main/templates/main/partials/potty_row.html | 21 ++ .../main/partials/potty_section.html | 51 +++++ main/tests.py | 3 + main/urls.py | 18 ++ main/views.py | 191 ++++++++++++++++++ manage.py | 22 ++ requirements.txt | 4 + 45 files changed, 922 insertions(+) create mode 100644 baby_tracker/__init__.py create mode 100644 baby_tracker/__pycache__/__init__.cpython-313.pyc create mode 100644 baby_tracker/__pycache__/settings.cpython-313.pyc create mode 100644 baby_tracker/__pycache__/urls.cpython-313.pyc create mode 100644 baby_tracker/__pycache__/wsgi.cpython-313.pyc create mode 100644 baby_tracker/asgi.py create mode 100644 baby_tracker/settings.py create mode 100644 baby_tracker/urls.py create mode 100644 baby_tracker/wsgi.py create mode 100644 db.sqlite3 create mode 100644 main/__init__.py create mode 100644 main/__pycache__/__init__.cpython-313.pyc create mode 100644 main/__pycache__/admin.cpython-313.pyc create mode 100644 main/__pycache__/apps.cpython-313.pyc create mode 100644 main/__pycache__/forms.cpython-313.pyc create mode 100644 main/__pycache__/models.cpython-313.pyc create mode 100644 main/__pycache__/urls.cpython-313.pyc create mode 100644 main/__pycache__/views.cpython-313.pyc create mode 100644 main/admin.py create mode 100644 main/apps.py create mode 100644 main/forms.py create mode 100644 main/migrations/0001_initial.py create mode 100644 main/migrations/0002_alter_feeding_amount.py create mode 100644 main/migrations/0003_alter_feeding_amount_alter_feeding_duration.py create mode 100644 main/migrations/__init__.py create mode 100644 main/migrations/__pycache__/0001_initial.cpython-313.pyc create mode 100644 main/migrations/__pycache__/0002_alter_feeding_amount.cpython-313.pyc create mode 100644 main/migrations/__pycache__/0003_alter_feeding_amount_alter_feeding_duration.cpython-313.pyc create mode 100644 main/migrations/__pycache__/__init__.cpython-313.pyc create mode 100644 main/models.py create mode 100644 main/templates/main/base.html create mode 100644 main/templates/main/index.html create mode 100644 main/templates/main/partials/add_feed.html create mode 100644 main/templates/main/partials/add_potty.html create mode 100644 main/templates/main/partials/edit_feed_row.html create mode 100644 main/templates/main/partials/edit_potty_row.html create mode 100644 main/templates/main/partials/feed_row.html create mode 100644 main/templates/main/partials/feed_section.html create mode 100644 main/templates/main/partials/potty_row.html create mode 100644 main/templates/main/partials/potty_section.html create mode 100644 main/tests.py create mode 100644 main/urls.py create mode 100644 main/views.py create mode 100644 manage.py create mode 100644 requirements.txt diff --git a/baby_tracker/__init__.py b/baby_tracker/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/baby_tracker/__pycache__/__init__.cpython-313.pyc b/baby_tracker/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b4324710d6c44d18661c4210f2b05f626118717f GIT binary patch literal 170 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 Vf*h!4!Z0Ycp!3;^2A|T>{{afiHWdH> literal 0 HcmV?d00001 diff --git a/main/__init__.py b/main/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/__pycache__/__init__.cpython-313.pyc b/main/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c844b6d858414f05596adbe85c27c2ee8099a37d GIT binary patch literal 162 zcmey&%ge<81Us2R(n0iN5CH>>P{wB#AY&>+I)f&o-%5reCLr%KNa~iOvsFxJacWU< zOev6z2`I|XN=+^)j!8;Ps*EowN=(iMilT6G6EpK-;^Q;(GE3s)^$IF)aoFVMr`f8$ z8jwK#Lhk;NfD-77f_lg;u=xRY&Fq@!MYLePsp_h!uO2<4>1mH>`S{^k@2*M6H#8<< zkCoAPt?ZM41azIOQJ`}qFamSkSTn&~v%s1o*T@11tQ#b-L%LOFoFu8<%Q`m-ININ= z^ozJPbJ42w&XJK7#H2~qc@KK;$eq9hN?(Jl3d;OZnLV6OtV{*HWY-FyAy)FI8q zx2tev67b&>ZHzZl&GfR)=i7kyPc?R`oiRD=bLB)?G03HI;{oWFi@Y4EZ^2D00apjN z5pdAu1U3NcE!C>bt7u-I05bjRXtV05GwBGUHhfPt1>VEk02M2)<-8K*-mjM5fwp$wB@{0-oSKxMnd&|eI_ED>iah*To9v_6C I$(@q?Cu+v*ZU6uP literal 0 HcmV?d00001 diff --git a/main/__pycache__/apps.cpython-313.pyc b/main/__pycache__/apps.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21168b32b96843199171cdacca741736106fe685 GIT binary patch literal 522 zcmY*Vv1%JZ5Z%2yDY6t1OR(uZzN-jTP!a~`m`|dSR>4pXXP{AzF6j3^VP_3w zQK()qLwo5Z*fmv~;1|2uIk@(=Zd#q6N4Wl+Kl5GFT3x{wqrH7qZilIi9b%^OsapFB dz9wnUt~LlBT+aC|d-qs(c=z|tKSp6$^#uL-iMRj& literal 0 HcmV?d00001 diff --git a/main/__pycache__/forms.cpython-313.pyc b/main/__pycache__/forms.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca2d16cf27fde0459e171018707b4d5fddbb7d5e GIT binary patch literal 1894 zcmbVNOK%)S5bk;J%U(b5`mx5ISQvW}*oA`+AS(h{n8Zn}Bn=XWRYv38_A+61#&plh zI6ok=#DyS5mV7ZseB*@jGaN3gT0$V@5KT z+)W~;u034PQj41j(*&mVA55#6ak7W#<|xuwk9bQQDmYT5wai$<51Z1s9mVlhJ&m2B z-W?pzgYlTu2v;cKDpk0aq*fudwxFggu2Y>GO~Wx|z8iBH5*=cYGf}g>sK5RzY7HV( z;Xv*v+^ku52fEBtFE|>F>K`c7_(%c9(5b1eiHAo`YE{%O=dBAknNyt71)MC+(R@Y2 zNK~!pyg&=Qui5AH%YjpStlVO;cZel+bXizW57dpfHkdTMR@4q-nQ64S7yD5tjWCLt zkVZZ5gm_WFV!U6E!k9dBcW;>5G%hiypyqWo#2;p1w&z)qH9&qo{S*g3@Z+Siic zd;~M-JlYidWEFOuaox~sG1rwj*KI|Oc7S%lb-!(UL3gI;y6Zj{ao~q6j9i!F!AJwx zERg29&w_^Fm_(YC1*{&+{A#uzYE4`i&-wg&c8R5yL^& zT|6j%4Yva+CLr7~{D{1|^l|M=!MLck0c*E;bRSZP+M2hv<;L8re*<673|gKa))Gxr zHnyaWwd8pSh07Kk;34S@jBXop@RM!xugOb$H+OITVm+BUs9t+IdA(CA|6ZE=tu)se zpX*F79T{4+|A=U##pf9^KDAfeEhZDoy@_$0D3y2a{dg~#SnQ0AA6fbpaMDY~qmklp z?t6>RL0ax0;LcX}O%d1GH|wLF)#!XohA%qrjrMipoK; zJl`xheX{@6%2I{mDakyDP52^aVSS6^4U={{-Xwe&0q+7niZBKMGW!tigqak>DV$pj z6Is&;HUc&{zl87(!YsmhrAlg8g;|U(mH@EbMz)R4(DYBE2ZIjuT-n}R++F;6^GW|f z<@2ZIYn_pai~7f~&g&n38PmVkB=6xj1gzStCdpxw0HjTV)2mKKnvMHj*o?ZeO{6Rm zU31*F%-%wAV+*9MmxMl>PG%O<`{F8J02loC5mx}7Yl@=$LB{?hGbj46lKWwHr~0UR VLclz^oQJWoQ+!nXn}C@t=_Qa5oU{M{ literal 0 HcmV?d00001 diff --git a/main/__pycache__/models.cpython-313.pyc b/main/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b87ed9d2d71782998423e1788bbfa56ad581791 GIT binary patch literal 1968 zcmcIl%}*Og6rc5e_yaEnyAVnVp+KctEx1XFD*D}Eo6-=MvP5lFORKd#7$@spcXqAB zJ^2(Rr<}Ow2sh`H{s}$WX{~!_aJ5F9Txj#6q!C;?gL=$e4uLLH{4UMPBJkbKvL=*GEHpIBtRz%;zM2{%} zQ~nR8R92F~V_cRLxKg!C)O3o2asN*37qIS=JYj-HSU?k)s0B1J6<|_c-i{6~@yC#= zq{*uS3xa>_QooXywBTxhg@N(fr3?vTgn%&ujH!QRsKA){2SymOh-r~&!p5`_HeQY< zRUXVzTB=y(V+9r^16(QCu4_`R-12(Q!l>c6VDb8$LxD$)x@+r}{XjQLrDMF$!vK#| zjfc8Pt+KnvgT+0&Qlt(nm#n&Ja=Bm{*8M|)#erND1`@=(!r$rV0Q=-F*&g(Q4cm&} zkx{4!UGdw@`8r^Ji`n;R(RK0#qtMV@W)$y(b!bvGDpuaFmgQQ52X)cmqo8Ze8E`ek-FfJX)@% z4VUh~uCo`vh1d2B=FNF@@R)ccYubkEdlaK;*DaSvH!PQyX`de|)tTW|Y>S6? z=)*o$wrrO=>g=<0OX{dA z&1^3=(T&X?#pVyBR=N{gZGPE{#=Fs(qv*`D_dC(Io0)S-kk)iM6?hHbVLiYXgQJ` z;qn#;v2i>J{2ev|czgpODMN|Nj%`*-T-LBdsX6wp%OwpEX37J&bk^X?w_Xnxu|_Eu zwvqK8d=l;hu(6=@lizx6K!$Um{*Lson{^lG2+< z8IaOaC%*JDo@$T3*AiRl7rE!T_RY0+EZq*J{Ts%r%OzEI4SF_*fFT%$@YKN;afF&+ zZvpU;qHQ@9$E8-W!QMghy9k&HTSB-{#woNR;1xMv06ZeSvB}}OjZbys^GEUdgTkLg z`AGSLD2ZV6_Q@!L^1WD^nSN@>Y-)^b*eu<#F1Fidc8jnV z;|)*3!N3vY!TJq2`Vl&(#!WbR;-=vXIJ1;(!DSDxGw=Q8?R0nNA`s{Y^!oNnDrF%6 zzuDyK3bzLrCI`S5zyqGkgB1>QNx=8;u6)mm3%im);3fbM1=qUgYGLP>ck{jTE=%-L zVcn}!Wh1`N79J}6*Q=KB+M=I|0SDo;g`bL`g9zASfQqYs)&==NTLh^X>MFH|e9#sl zDux|I*cK5gMjgbEE$&bea}dL}7@=a!L5$iWN=3p!L~RkHBIzJvOw0sus1#3+oimW; zOjwijx99X_vx$30LGLvan1MG4$%FX*PBead~q`Y>)h}LVebW5+Ul94D%Y7v!1d*zKA2XEF*FWYaes_T13yuB-H zcDc|RT3hya7mcWO14r23DH-wh-W;L7yJ#f4cjo9r{|PgKc5799`S7e)QPg(Ka68GG zC`c1&?nOFGpZT_=ma5ZrT-LCQzD(T9f|~}@t*A2E#a@53;}x z5e~7y4hxR3zz&7!qkZXjq9d$oKfnb|0rTPGoKVmZ)`U8Z!Wyn_qoS?}Thi8^sAH-4 zj%Ke-Dw3iKY=_geJ=3#Lsmk>-TEubMjeUO_r16i7JJ*+nJ1U|5qr5f(mWR6VcekKT9>vWnUsku{uz?Iunrcr23 zEt9F`W`2`E(PD`ccPlwhlJm_+1p;4Mxx2^p)_9hTXPb-b1oD641A{#ueK<;=#y^Sd Bc%lFR literal 0 HcmV?d00001 diff --git a/main/__pycache__/views.cpython-313.pyc b/main/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3eb3c95e1eca3d3f5f808769372c0e961566f379 GIT binary patch literal 8596 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 RwlBGQw(eE0m#w4U`9DKNDLeoG literal 0 HcmV?d00001 diff --git a/main/admin.py b/main/admin.py new file mode 100644 index 0000000..97ce168 --- /dev/null +++ b/main/admin.py @@ -0,0 +1,23 @@ +# admin.py +from django.contrib import admin +from .models import Feeding, Potty + + + +class PottyAdmin(admin.ModelAdmin): + # Show timestamp in the list view + list_display = ('timestamp', 'consistency', 'notes') # Add timestamp here + + # Allow timestamp to be editable in the form view + fields = ('consistency', 'notes') # Add timestamp here to the edit form + +admin.site.register(Potty, PottyAdmin) + +class FeedingAdmin(admin.ModelAdmin): + # Show timestamp in the list view + list_display = ('timestamp', 'feeding_type', 'amount', 'duration' , 'notes') # Add timestamp here + + # Allow timestamp to be editable in the form view + fields = ('feeding_type', 'amount', 'duration' , 'notes') # Add timestamp here to the edit form + +admin.site.register(Feeding, FeedingAdmin) \ No newline at end of file diff --git a/main/apps.py b/main/apps.py new file mode 100644 index 0000000..167f044 --- /dev/null +++ b/main/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MainConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'main' diff --git a/main/forms.py b/main/forms.py new file mode 100644 index 0000000..f501e0f --- /dev/null +++ b/main/forms.py @@ -0,0 +1,37 @@ +from django import forms +from .models import Feeding, Potty + +class FeedingForm(forms.ModelForm): + class Meta: + model = Feeding + fields = ['feeding_type', 'amount', 'duration', 'notes'] + widgets = { + 'feeding_type': forms.Select(attrs={'class': 'form-control'}), + 'amount': forms.NumberInput(attrs={ + 'class': 'form-control', + 'placeholder': 'Enter amount (if bottle) in ounces' + }), + 'duration': forms.TextInput(attrs={ + 'class': 'form-control', + 'placeholder': 'Enter duration (if breast) in minutes' + }), + 'notes': forms.Textarea(attrs={ + 'class': 'form-control', + 'placeholder': 'Additional notes (optional)', + 'rows': 3 + }), + } + +class PottyForm(forms.ModelForm): + class Meta: + model = Potty + fields = ['consistency', 'notes'] + widgets = { + 'consistency': forms.Select(attrs={'class': 'form-control'}), + 'notes': forms.Textarea(attrs={ + 'class': 'form-control', + 'placeholder': 'Additional notes (optional)', + 'rows': 3 + }) + } + diff --git a/main/migrations/0001_initial.py b/main/migrations/0001_initial.py new file mode 100644 index 0000000..233a7f0 --- /dev/null +++ b/main/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# Generated by Django 5.1.4 on 2024-12-07 10:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Feeding', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('feeding_type', models.CharField(choices=[('bottle', 'Bottle'), ('breast', 'Breast')], max_length=10)), + ('amount', models.FloatField(blank=True, null=True)), + ('duration', models.FloatField(blank=True, null=True)), + ('notes', models.TextField(blank=True)), + ], + ), + migrations.CreateModel( + name='Potty', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('consistency', models.CharField(choices=[('solid', 'Solid'), ('soft', 'Soft'), ('watery', 'Watery'), ('pee', 'Pee'), ('other', 'Other')], max_length=50)), + ('notes', models.TextField(blank=True)), + ], + ), + ] diff --git a/main/migrations/0002_alter_feeding_amount.py b/main/migrations/0002_alter_feeding_amount.py new file mode 100644 index 0000000..5dcbc53 --- /dev/null +++ b/main/migrations/0002_alter_feeding_amount.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.4 on 2024-12-07 18:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='feeding', + name='amount', + field=models.IntegerField(blank=True, null=True), + ), + ] diff --git a/main/migrations/0003_alter_feeding_amount_alter_feeding_duration.py b/main/migrations/0003_alter_feeding_amount_alter_feeding_duration.py new file mode 100644 index 0000000..6fb4fdf --- /dev/null +++ b/main/migrations/0003_alter_feeding_amount_alter_feeding_duration.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.4 on 2024-12-07 18:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0002_alter_feeding_amount'), + ] + + operations = [ + migrations.AlterField( + model_name='feeding', + name='amount', + field=models.FloatField(blank=True, null=True), + ), + migrations.AlterField( + model_name='feeding', + name='duration', + field=models.IntegerField(blank=True, null=True), + ), + ] diff --git a/main/migrations/__init__.py b/main/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/migrations/__pycache__/0001_initial.cpython-313.pyc b/main/migrations/__pycache__/0001_initial.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b3c70a7b65ffa269da800244692bedd8bfc90a5 GIT binary patch literal 1715 zcmb_cOKclO7@l44ZfwU+>@-g&F$sz)IVyRn6eW}*nh-=v+caxHsw|Dx-mx>ude_X3 zlbTZ{B+k7c<=88?9DC%*aqWw(IaT76n@gy;^3U24K_mhsM%wuw`_26CIZr0z2-e!o ze8tug`b7#C3*>N}-vjakGLfk~KsyRkc2uU$p-J>EGSv(+BL!v8=wmOD_ai-lMJifO zKa)aE74a&qFpE>q^@UOOY~uK(ONUUhFPsO8G+IDRF%eTug+)x2Y0HS|1!HgM@{t}7 z&O}VD5ZxQO@}Fv|rfwSMz`Ax@HKTwVy#^OsR{#+Q#Q2qnK{K(enn`nLT?O1Q;3luc zNsFlvll~W&5x``wx#x!TXxT7F*VSudANwC;AHOd4Wn@k~QOwDH?EmbuCVgI3*^oKK zhAWxew1_>tsQ;PlnYoYZ;4185mxkkf?cahM2yoa@wrv4<&^#fu6K+r+ZKs(&jjX;8i5`(iXP_<5yt(H zh8nQtbI^qJOb!L82TJ=MEfF8O)_R5=;#T;+Fs!OqcRBpli;m?U3eBxMj)>azUSA8{ z^*Hf!3X}B&m=^kHlqqp+U+BAFv>^sdFagx(#4R;)y1dNy9BK>QltiBLy)qY?2|Gx} zF{FYugz|6mgH;=%>IZTXoLic?pbTbwgmtV0$tX77QS zbNGzV`5wI<8hQR%S5rof=U;TAD0ZVA&93 zCp~p?r#*eEHGS*!_A9$Ny&0soI_c??uiCRqt=Xm1JX|x|yJqs_W;?Uk$}FCaHZymE z)Cb+@qIY`@d5?VzB4i%< gGq80dilY2(ASL&kF{2nS;_cKzGqvy*fe@bl1Ie$wzyJUM literal 0 HcmV?d00001 diff --git a/main/migrations/__pycache__/0002_alter_feeding_amount.cpython-313.pyc b/main/migrations/__pycache__/0002_alter_feeding_amount.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5edf86bd0f339d5c22f62842615fb98310848ed8 GIT binary patch literal 790 zcmZuvO=}ZD7@pa$WY-kas8~NLRocT|Y7}~?mVzjPQHx~iZS640PL^pmvvGFz(3>E5 z7NPzIz4=$#OTt_|^%jZZ)tPKU6dc%hpXdGB_kCt3OG^RJXY2ER@(BX)-H`clXJE3c z!3jVB!RMd_1#DTuS_3QK4nWp*fb0miy?N2%y=9kJ*ohOm=Z1uq3i>P&M6!(M%Ijw_ zP4n)e1^|CXCI=dvfCvbPfUpo0HnQ$Q;Y4n`_IE*v^(Z!SqDs5|-D7S1`_{*13y`l!A2%NppQD=C zapp3PoXc(hN_*+#E2rIx3gU{Lv?@#!Sn|vJKEF?X{$9p&b2gBx_xUi~(*XFUz;v0D zWV|DjbKn6Fz5@G@!F`Qs%U}UK2A*~wc)Aap)>Jh6KGTbw>7n78R|>eAusc!6Fpm zYF=qm|A)RT_0IqF8yd5{3af^;TNRZz)7M-n2ju&V4vwf;Y&05A5RN%v=!lRYq9MYa zB%@rECRkVnaVSM*E5`Ih7&MDxSC<|sUl7F|A~_Y!qlmw)}S~VX2?V=)YyjF=_ME zZ{gM%;taP>B>NXo=J~Tf#FsWcz0t;Nmf%X`b0^NW|x!q8b6I4ix?i^ION^}S?N?CVtz@~X9gv(|fg!TZj3Q8ia} ztPlHaX?o{@Ylup4jA@vx2d&)R+|r^eWld50NM@qET?}o9ElUXHP9MrJ(jkPuECAgf U);zR6*~9v3zrOktNRX?40}KrHy#N3J literal 0 HcmV?d00001 diff --git a/main/migrations/__pycache__/__init__.cpython-313.pyc b/main/migrations/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8ffdafa2134e235473f99610c8cdde8698fbfdf GIT binary patch literal 173 zcmey&%ge<81Us2R(n0iN5CH>>P{wB#AY&>+I)f&o-%5reCLr%KNa~i4vsFxJacWU< zOev6z2`I|XN=+^)j!8;Ps*EowN=(iMilT6G6EpK-ax>G55=%1k^NM5Q<1_OzOXB18 i3My}L*yQG?l;)(`6|n*h2U%VWVtiy~WMnL22C@Jcc`d{M literal 0 HcmV?d00001 diff --git a/main/models.py b/main/models.py new file mode 100644 index 0000000..acde26f --- /dev/null +++ b/main/models.py @@ -0,0 +1,34 @@ +from django.db import models + +# Create your models here. +from django.db import models + +class Feeding(models.Model): + FEEDING_TYPES = [ + ('bottle', 'Bottle'), + ('breast', 'Breast'), + ] + + timestamp = models.DateTimeField(auto_now_add=True) + feeding_type = models.CharField(max_length=10, choices=FEEDING_TYPES) + amount = models.FloatField(null=True, blank=True) # Store ounces for bottle feed + duration = models.IntegerField(null=True, blank=True) # Store duration in minutes for breastfeed + notes = models.TextField(blank=True) + + def __str__(self): + return f"{self.get_feeding_type_display()} - {self.timestamp}" + + +class Potty(models.Model): + timestamp = models.DateTimeField(auto_now_add=True) + consistency = models.CharField(max_length=50, choices=[ + ('solid', 'Solid'), + ('soft', 'Soft'), + ('watery', 'Watery'), + ('pee', 'Pee'), + ('other', 'Other'), + ]) + notes = models.TextField(blank=True) + + def __str__(self): + return f"{self.get_potty_type_display()} - {self.timestamp}" diff --git a/main/templates/main/base.html b/main/templates/main/base.html new file mode 100644 index 0000000..36b426f --- /dev/null +++ b/main/templates/main/base.html @@ -0,0 +1,36 @@ + + + + + + + Baby Tracker + + + + + + + + + + +
+
+

Caelum's Poop and Feed Tracker

+
+
+ {% block content %}{% endblock %} +
+
+ + + + + + + + \ No newline at end of file diff --git a/main/templates/main/index.html b/main/templates/main/index.html new file mode 100644 index 0000000..a90c408 --- /dev/null +++ b/main/templates/main/index.html @@ -0,0 +1,5 @@ +{% extends 'main/base.html' %} +{% block content %} +{% include 'main/partials/feed_section.html' %} +{% include 'main/partials/potty_section.html' %} +{% endblock %} \ No newline at end of file diff --git a/main/templates/main/partials/add_feed.html b/main/templates/main/partials/add_feed.html new file mode 100644 index 0000000..9ede11e --- /dev/null +++ b/main/templates/main/partials/add_feed.html @@ -0,0 +1,40 @@ +
+ {% csrf_token %} +
+ {{ form.feeding_type.label_tag }} + {{ form.feeding_type }} +
+ + +
+ {{ form.notes.label_tag }} + {{ form.notes }} +
+ + +
+ + diff --git a/main/templates/main/partials/add_potty.html b/main/templates/main/partials/add_potty.html new file mode 100644 index 0000000..43b593c --- /dev/null +++ b/main/templates/main/partials/add_potty.html @@ -0,0 +1,13 @@ +
+ {% csrf_token %} +
+ {{form.consistency.label_tag}} + {{form.consistency}} +
+
+ {{form.notes.label_tag}} + {{form.notes}} +
+ + +
\ No newline at end of file diff --git a/main/templates/main/partials/edit_feed_row.html b/main/templates/main/partials/edit_feed_row.html new file mode 100644 index 0000000..45f907d --- /dev/null +++ b/main/templates/main/partials/edit_feed_row.html @@ -0,0 +1,37 @@ + + + + + + {% if feeding.feeding_type == 'bottle' %} + + {% elif feeding.feeding_type == 'breast' %} + + {% else %} + + {% endif %} + + + + + + + + + + + diff --git a/main/templates/main/partials/edit_potty_row.html b/main/templates/main/partials/edit_potty_row.html new file mode 100644 index 0000000..9d50c33 --- /dev/null +++ b/main/templates/main/partials/edit_potty_row.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + diff --git a/main/templates/main/partials/feed_row.html b/main/templates/main/partials/feed_row.html new file mode 100644 index 0000000..3edce0d --- /dev/null +++ b/main/templates/main/partials/feed_row.html @@ -0,0 +1,30 @@ + + {{ feeding.timestamp }} + + {% if feeding.feeding_type == 'breast' %} + {{ feeding.duration }} min + {% else %} + {{ feeding.amount }} oz + {% endif %} + + {{ feeding.notes }} + + + + + + + + + diff --git a/main/templates/main/partials/feed_section.html b/main/templates/main/partials/feed_section.html new file mode 100644 index 0000000..bfd7300 --- /dev/null +++ b/main/templates/main/partials/feed_section.html @@ -0,0 +1,58 @@ +
+
+

Feed Records

+ +
+ +
+ + + + + + + + + + + + {% for feeding in feedings %} + + + + + + + {% endfor %} + + +
DateAmount or DurationNotesActions
{{ feeding.timestamp }}{% if feeding.feeding_type == 'breast' %}{{feeding.duration}} min{% else %}{{feeding.amount}} oz{% endif %}{{feeding.notes}} + + +
+
+ + + + +
+
+ diff --git a/main/templates/main/partials/potty_row.html b/main/templates/main/partials/potty_row.html new file mode 100644 index 0000000..6e28b83 --- /dev/null +++ b/main/templates/main/partials/potty_row.html @@ -0,0 +1,21 @@ + + {{ potty.timestamp }} + {{ potty.consistency }} + {{ potty.notes }} + + + + + \ No newline at end of file diff --git a/main/templates/main/partials/potty_section.html b/main/templates/main/partials/potty_section.html new file mode 100644 index 0000000..d350739 --- /dev/null +++ b/main/templates/main/partials/potty_section.html @@ -0,0 +1,51 @@ +
+
+

Potty Records

+ +
+
+ + + + + + + + + + + + {% for potty in potties %} + + + + + + + {% endfor %} + + +
DateTypeNotesActions
{{ potty.timestamp }}{{ potty.consistency }}{{ potty.notes }} + + +
+
+ + + +
+
\ No newline at end of file diff --git a/main/tests.py b/main/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/main/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/main/urls.py b/main/urls.py new file mode 100644 index 0000000..decac41 --- /dev/null +++ b/main/urls.py @@ -0,0 +1,18 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.index, name='feedings_list'), + path('add_feed', views.add_feed, name='add_feed'), + path('delete_feed/', views.delete_feed, name='delete_feed'), + path('edit_feed/', views.edit_feed, name='edit_feed'), + path('update_feed/', views.update_feed, name='update_feed'), + path('cancel_edit_feed/', views.cancel_edit_feed, name='cancel_edit_feed'), + path('add_potty', views.add_potty, name='add_potty'), + path('delete_potty/', views.delete_potty, name='delete_potty'), + path('edit_potty/', views.edit_potty, name='edit_potty'), + path('update_potty/', views.update_potty, name='update_potty'), + path('cancel_edit_potty/', views.cancel_edit_potty, name='cancel_edit_potty'), + path('export_feedings_csv', views.export_feedings_csv, name='export_feedings_csv'), + path('export_potties_csv', views.export_potties_csv, name='export_potties_csv'), +] diff --git a/main/views.py b/main/views.py new file mode 100644 index 0000000..71d972c --- /dev/null +++ b/main/views.py @@ -0,0 +1,191 @@ +from django.shortcuts import render, get_object_or_404 +from .models import Feeding, Potty +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt +from .forms import FeedingForm, PottyForm + + +def index(request): + context = {} + + feedings = Feeding.objects.all().order_by('-timestamp') + + context['feedings'] = feedings + + # Grab all objects sorted by timestamp (most recent first) + potties = Potty.objects.all().order_by('-timestamp') + + + context['potties'] = potties + + return render(request, 'main/index.html', context) + + +def add_feed(request): + context = {} + if request.method == 'POST': + form = FeedingForm(request.POST) + if form.is_valid(): + feeding_type = form.cleaned_data['feeding_type'] + amount = form.cleaned_data['amount'] + duration = form.cleaned_data['duration'] + # Validate based on feeding type + if feeding_type == 'bottle' and not amount: + form.add_error('amount', 'Amount is required for bottle feeding.') + elif feeding_type == 'breast' and not duration: + form.add_error('duration', 'Duration is required for breast feeding.') + else: + form.save() + feedings = Feeding.objects.all().order_by('-timestamp') + context['feedings'] = feedings + return render(request, 'main/partials/feed_section.html', context) + + else: + form = FeedingForm() + + return render(request, 'main/partials/add_feed.html', {'form': form}) + + +@csrf_exempt +def delete_feed(request, feed_id): + context = {} + if request.method == "DELETE": + feed = get_object_or_404(Feeding, id=int(feed_id)) + feed.delete() + feedings = Feeding.objects.all().order_by('-timestamp') + context['feedings'] = feedings + return render(request, 'main/partials/feed_section.html', context) # Return a success response + return HttpResponse(status=405) # Method not allowed + +from django.shortcuts import get_object_or_404, render + +@csrf_exempt +def edit_feed(request, feed_id): + feed = get_object_or_404(Feeding, id=feed_id) + return render(request, 'main/partials/edit_feed_row.html', {'feeding': feed}) + + +@csrf_exempt +def update_feed(request, feed_id): + + if request.method == "POST": + feed = get_object_or_404(Feeding, id=feed_id) + feed.timestamp = request.POST['timestamp'] + if feed.feeding_type == 'bottle': + feed.amount = float(request.POST['amount_or_duration']) + else: + feed.duration = int(float(request.POST['amount_or_duration'])) + feed.notes = request.POST['notes'] + feed.save() + return render(request, 'main/partials/feed_row.html', {'feeding': feed}) + +def cancel_edit_feed(request, feed_id): + feed = get_object_or_404(Feeding, id=feed_id) + return render(request, 'main/partials/feed_row.html', {'feeding': feed}) + +def add_potty(request): + context = {} + if request.method == 'POST': + form = PottyForm(request.POST) + if form.is_valid(): + form.save() + potties = Potty.objects.all().order_by('-timestamp') + context['potties'] = potties + return render(request, 'main/partials/potty_section.html', context) + else: + form = PottyForm() + + return render(request, 'main/partials/add_potty.html', {'form': form}) + +@csrf_exempt +def delete_potty(request, potty_id): + context = {} + if request.method == 'DELETE': + potty = get_object_or_404(Potty, id=int(potty_id)) + potty.delete() + potties = Potty.objects.all().order_by('-timestamp') + context['potties'] = potties + return render(request, 'main/partials/potty_section.html', context) + return HttpResponse(status=405) + +@csrf_exempt +def edit_potty(request, potty_id): + context = {} + potty = get_object_or_404(Potty, id=potty_id) + context['potty'] = potty + form = PottyForm(potty) + context['form'] = form + return render(request, 'main/partials/edit_potty_row.html', context) + + +@csrf_exempt +def update_potty(request, potty_id): + context = {} + if request.method == 'POST': + potty = get_object_or_404(Potty, id=potty_id) + potty.timestamp = request.POST['timestamp'] + potty.consistency = request.POST['consistency'] + potty.notes = request.POST['notes'] + potty.save() + return render(request, 'main/partials/potty_row.html', {'potty': potty}) + + +def cancel_edit_potty(request, potty_id): + potty = get_object_or_404(Potty, id=potty_id) + return render(request, 'main/partials/potty_row.html', {'potty': potty}) + +import csv +from django.http import HttpResponse + +def export_feedings_csv(request): + # Create the HTTP response with CSV headers + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="feedings.csv"' + + # Create a CSV writer + writer = csv.writer(response) + # Write the header row + writer.writerow(['Timestamp', 'Feeding Type', 'Amount', 'Duration', 'Notes']) + + # Fetch the data from the database + feedings = Feeding.objects.all().order_by('-timestamp') + for feeding in feedings: + writer.writerow([ + feeding.timestamp, + feeding.get_feeding_type_display(), # Use readable choices if applicable + feeding.amount if feeding.amount else "", + feeding.duration if feeding.duration else "", + feeding.notes, + ]) + + return response + +def export_potties_csv(request): + # Create the HTTP response with CSV headers + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="potties.csv"' + + # Create a CSV writer + writer = csv.writer(response) + # Write the header row + writer.writerow(['Timestamp', 'Consistency', 'Notes']) + + # Fetch the potty data from the database + potties = Potty.objects.all().order_by('-timestamp') + for potty in potties: + writer.writerow([ + potty.timestamp, + potty.get_consistency_display() if potty.consistency else "", + potty.notes, + ]) + + return response + + + + + + + + + diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..6c1bf8a --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'baby_tracker.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fe37b57 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +asgiref==3.8.1 +Django==5.1.4 +sqlparse==0.5.2 +tzdata==2024.2