Seth0330 commited on
Commit
1b8f2e5
·
verified ·
1 Parent(s): 4e3c83e

Update frontend/src/components/admin/PlanForm.jsx

Browse files
frontend/src/components/admin/PlanForm.jsx CHANGED
@@ -4,6 +4,7 @@ import React, { useEffect, useState } from "react";
4
  const BILLING_OPTIONS = [
5
  { value: "monthly", label: "Monthly" },
6
  { value: "quarterly", label: "Quarterly" },
 
7
  { value: "annual", label: "Annual" },
8
  ];
9
 
@@ -51,108 +52,113 @@ export default function PlanForm({ plan, onSave, onCancel, isLoading }) {
51
  return (
52
  <form
53
  onSubmit={handleSubmit}
54
- className="grid grid-cols-1 md:grid-cols-2 gap-4 bg-stone-50 border border-stone-200 rounded-xl p-4"
55
  >
56
- <div className="space-y-2">
57
- <div>
58
- <label className="block text-xs font-medium text-stone-700 mb-1">
59
- Plan name
60
- </label>
61
- <input
62
- type="text"
63
- className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
64
- placeholder="Beginner Monthly"
65
- value={name}
66
- onChange={(e) => setName(e.target.value)}
67
- />
68
- </div>
 
 
69
 
70
- <div>
71
- <label className="block text-xs font-medium text-stone-700 mb-1">
72
- Billing period
73
- </label>
74
- <select
75
- className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
76
- value={billingPeriod}
77
- onChange={(e) => setBillingPeriod(e.target.value)}
78
- >
79
- {BILLING_OPTIONS.map((opt) => (
80
- <option key={opt.value} value={opt.value}>
81
- {opt.label}
82
- </option>
83
- ))}
84
- </select>
 
85
  </div>
86
 
87
- <div>
88
- <label className="block text-xs font-medium text-stone-700 mb-1">
89
- Price (CAD)
90
- </label>
91
- <input
92
- type="number"
93
- className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
94
- placeholder="99"
95
- value={price}
96
- onChange={(e) => setPrice(e.target.value)}
97
- min="0"
98
- step="0.01"
99
- />
100
- </div>
 
101
 
102
- <div>
103
- <label className="block text-xs font-medium text-stone-700 mb-1">
104
- Max Students
105
- </label>
106
- <input
107
- type="number"
108
- className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
109
- placeholder="1"
110
- value={maxStudents}
111
- onChange={(e) => setMaxStudents(e.target.value)}
112
- min="1"
113
- />
 
114
  </div>
115
  </div>
116
 
117
- <div className="space-y-2">
118
- <div>
119
- <label className="block text-xs font-medium text-stone-700 mb-1">
120
- Description
121
- </label>
122
- <textarea
123
- className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 min-h-[60px]"
124
- placeholder="Beginner classes 2x per week."
125
- value={description}
126
- onChange={(e) => setDescription(e.target.value)}
127
- />
128
- </div>
129
 
130
- <div className="flex items-center justify-between pt-1">
131
- <label className="inline-flex items-center gap-2 text-xs text-stone-700">
132
- <input
133
- type="checkbox"
134
- className="rounded border-stone-300"
135
- checked={isActive}
136
- onChange={(e) => setIsActive(e.target.checked)}
137
- />
138
- Active / visible to students
139
- </label>
140
- <div className="flex gap-2">
141
- <button
142
- type="button"
143
- onClick={onCancel}
144
- className="px-3 py-1.5 rounded-lg border border-stone-200 text-xs font-medium text-stone-700 hover:bg-stone-100"
145
- >
146
- Cancel
147
- </button>
148
- <button
149
- type="submit"
150
- disabled={isLoading}
151
- className="px-3 py-1.5 rounded-lg bg-indigo-600 text-white text-xs font-medium hover:bg-indigo-700 disabled:opacity-60"
152
- >
153
- {isLoading ? "Saving…" : plan ? "Update plan" : "Create plan"}
154
- </button>
155
- </div>
156
  </div>
157
  </div>
158
  </form>
 
4
  const BILLING_OPTIONS = [
5
  { value: "monthly", label: "Monthly" },
6
  { value: "quarterly", label: "Quarterly" },
7
+ { value: "half_yearly", label: "Half Yearly" },
8
  { value: "annual", label: "Annual" },
9
  ];
10
 
 
52
  return (
53
  <form
54
  onSubmit={handleSubmit}
55
+ className="bg-stone-50 border border-stone-200 rounded-xl p-4 space-y-4"
56
  >
57
+ {/* Top Row: Plan Name, Billing Period on left; Price, Max Students on right */}
58
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
59
+ <div className="space-y-2">
60
+ <div>
61
+ <label className="block text-xs font-medium text-stone-700 mb-1">
62
+ Plan name
63
+ </label>
64
+ <input
65
+ type="text"
66
+ className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
67
+ placeholder="Beginner Monthly"
68
+ value={name}
69
+ onChange={(e) => setName(e.target.value)}
70
+ />
71
+ </div>
72
 
73
+ <div>
74
+ <label className="block text-xs font-medium text-stone-700 mb-1">
75
+ Billing period
76
+ </label>
77
+ <select
78
+ className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
79
+ value={billingPeriod}
80
+ onChange={(e) => setBillingPeriod(e.target.value)}
81
+ >
82
+ {BILLING_OPTIONS.map((opt) => (
83
+ <option key={opt.value} value={opt.value}>
84
+ {opt.label}
85
+ </option>
86
+ ))}
87
+ </select>
88
+ </div>
89
  </div>
90
 
91
+ <div className="space-y-2">
92
+ <div>
93
+ <label className="block text-xs font-medium text-stone-700 mb-1">
94
+ Price (CAD)
95
+ </label>
96
+ <input
97
+ type="number"
98
+ className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
99
+ placeholder="99"
100
+ value={price}
101
+ onChange={(e) => setPrice(e.target.value)}
102
+ min="0"
103
+ step="0.01"
104
+ />
105
+ </div>
106
 
107
+ <div>
108
+ <label className="block text-xs font-medium text-stone-700 mb-1">
109
+ Max Students
110
+ </label>
111
+ <input
112
+ type="number"
113
+ className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
114
+ placeholder="1"
115
+ value={maxStudents}
116
+ onChange={(e) => setMaxStudents(e.target.value)}
117
+ min="1"
118
+ />
119
+ </div>
120
  </div>
121
  </div>
122
 
123
+ {/* Description - Full Width */}
124
+ <div>
125
+ <label className="block text-xs font-medium text-stone-700 mb-1">
126
+ Description
127
+ </label>
128
+ <textarea
129
+ className="w-full rounded-lg border border-stone-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 min-h-[60px]"
130
+ placeholder="Beginner classes 2x per week."
131
+ value={description}
132
+ onChange={(e) => setDescription(e.target.value)}
133
+ />
134
+ </div>
135
 
136
+ {/* Bottom Row: Checkbox and Buttons */}
137
+ <div className="flex items-center justify-between pt-1">
138
+ <label className="inline-flex items-center gap-2 text-xs text-stone-700">
139
+ <input
140
+ type="checkbox"
141
+ className="rounded border-stone-300"
142
+ checked={isActive}
143
+ onChange={(e) => setIsActive(e.target.checked)}
144
+ />
145
+ Active / visible to students
146
+ </label>
147
+ <div className="flex gap-2">
148
+ <button
149
+ type="button"
150
+ onClick={onCancel}
151
+ className="px-3 py-1.5 rounded-lg border border-stone-200 text-xs font-medium text-stone-700 hover:bg-stone-100"
152
+ >
153
+ Cancel
154
+ </button>
155
+ <button
156
+ type="submit"
157
+ disabled={isLoading}
158
+ className="px-3 py-1.5 rounded-lg bg-indigo-600 text-white text-xs font-medium hover:bg-indigo-700 disabled:opacity-60"
159
+ >
160
+ {isLoading ? "Saving…" : plan ? "Update plan" : "Create plan"}
161
+ </button>
162
  </div>
163
  </div>
164
  </form>