|
2 | 2 | <html lang="en"> |
3 | 3 | <head> |
4 | 4 | <meta charset="UTF-8"> |
5 | | - <title>Search Page</title> |
| 5 | + <title>Routing Number Search</title> |
6 | 6 | <style> |
7 | 7 | body { |
8 | | - font-family: 'Segoe UI', Arial, sans-serif; |
9 | | - background: linear-gradient(135deg, #e3f0ff 0%, #f7f7f7 100%); |
| 8 | + font-family: 'Inter', system-ui, -apple-system, sans-serif; |
| 9 | + background: linear-gradient(145deg, #e6f0fa 0%, #f8fafc 100%); |
10 | 10 | display: flex; |
11 | 11 | justify-content: center; |
12 | 12 | align-items: center; |
13 | | - height: 100vh; |
| 13 | + min-height: 100vh; |
| 14 | + margin: 0; |
| 15 | + padding: 20px; |
| 16 | + box-sizing: border-box; |
14 | 17 | } |
15 | 18 | .search-container { |
16 | | - background: #fff; |
17 | | - padding: 32px 24px 24px 24px; |
18 | | - border-radius: 12px; |
19 | | - box-shadow: 0 4px 16px rgba(0,0,0,0.10); |
20 | | - min-width: 350px; |
| 19 | + background: #ffffff; |
| 20 | + padding: 2rem; |
| 21 | + border-radius: 16px; |
| 22 | + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); |
| 23 | + width: 100%; |
| 24 | + max-width: 400px; |
| 25 | + transition: transform 0.2s ease; |
| 26 | + } |
| 27 | + .search-container:hover { |
| 28 | + transform: translateY(-2px); |
21 | 29 | } |
22 | 30 | .search-title { |
23 | | - font-size: 1.4rem; |
24 | | - font-weight: 600; |
25 | | - color: #2d3a4b; |
26 | | - margin-bottom: 18px; |
| 31 | + font-size: 1.5rem; |
| 32 | + font-weight: 700; |
| 33 | + color: #1e293b; |
| 34 | + margin-bottom: 1.5rem; |
27 | 35 | text-align: center; |
| 36 | + letter-spacing: -0.02em; |
28 | 37 | } |
29 | 38 | .search-box { |
30 | 39 | display: flex; |
31 | | - gap: 8px; |
32 | | - margin-bottom: 20px; |
| 40 | + flex-direction: column; |
| 41 | + gap: 12px; |
33 | 42 | } |
34 | | - input[type="text"] { |
35 | | - flex: 1; |
36 | | - padding: 12px; |
| 43 | + select, input[type="text"] { |
| 44 | + padding: 12px 16px; |
37 | 45 | font-size: 1rem; |
38 | | - border: 1px solid #b0c4de; |
39 | | - border-radius: 6px; |
| 46 | + border: 1px solid #d1d5db; |
| 47 | + border-radius: 8px; |
| 48 | + background: #f8fafc; |
40 | 49 | outline: none; |
41 | | - transition: border-color 0.2s; |
42 | | - background: #f5faff; |
| 50 | + transition: border-color 0.2s, box-shadow 0.2s; |
| 51 | + } |
| 52 | + select:focus, input[type="text"]:focus { |
| 53 | + border-color: #2563eb; |
| 54 | + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); |
43 | 55 | } |
44 | | - input[type="text"]:focus { |
45 | | - border-color: #0078d4; |
| 56 | + select { |
| 57 | + appearance: none; |
| 58 | + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%236b7280' stroke-width='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E"); |
| 59 | + background-repeat: no-repeat; |
| 60 | + background-position: right 0.75rem center; |
| 61 | + background-size: 1.2em; |
46 | 62 | } |
47 | 63 | button { |
48 | | - padding: 12px 18px; |
49 | | - background: #0078d4; |
50 | | - color: #fff; |
| 64 | + padding: 12px; |
| 65 | + background: #2563eb; |
| 66 | + color: #ffffff; |
51 | 67 | border: none; |
52 | | - border-radius: 6px; |
| 68 | + border-radius: 8px; |
53 | 69 | font-size: 1rem; |
| 70 | + font-weight: 500; |
54 | 71 | cursor: pointer; |
55 | | - transition: background 0.2s; |
| 72 | + transition: background 0.2s, transform 0.1s; |
56 | 73 | } |
57 | 74 | button:hover { |
58 | | - background: #005fa3; |
| 75 | + background: #1d4ed8; |
| 76 | + transform: translateY(-1px); |
| 77 | + } |
| 78 | + button:active { |
| 79 | + transform: translateY(0); |
59 | 80 | } |
60 | 81 | .result-card { |
61 | | - background: #f5faff; |
62 | | - border: 1px solid #e0e7ef; |
63 | | - border-radius: 8px; |
64 | | - padding: 20px; |
65 | | - margin-top: 8px; |
66 | | - box-shadow: 0 2px 8px rgba(0,120,212,0.07); |
| 82 | + background: #f8fafc; |
| 83 | + border: 1px solid #e5e7eb; |
| 84 | + border-radius: 12px; |
| 85 | + padding: 1.25rem; |
| 86 | + margin-top: 1rem; |
| 87 | + transition: box-shadow 0.2s; |
| 88 | + } |
| 89 | + .result-card:hover { |
| 90 | + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); |
67 | 91 | } |
68 | 92 | .result-title { |
69 | | - font-size: 1.1rem; |
70 | | - font-weight: 500; |
71 | | - color: #0078d4; |
72 | | - margin-bottom: 10px; |
| 93 | + font-size: 1.125rem; |
| 94 | + font-weight: 600; |
| 95 | + color: #2563eb; |
| 96 | + margin-bottom: 0.75rem; |
73 | 97 | } |
74 | 98 | .result-row { |
75 | | - margin-bottom: 7px; |
76 | | - color: #2d3a4b; |
| 99 | + margin-bottom: 0.5rem; |
| 100 | + color: #1e293b; |
| 101 | + font-size: 0.95rem; |
77 | 102 | } |
78 | 103 | .result-label { |
79 | 104 | font-weight: 500; |
80 | | - color: #5a6b7b; |
| 105 | + color: #4b5563; |
81 | 106 | } |
82 | 107 | .error-msg { |
83 | | - color: #d32f2f; |
84 | | - margin-top: 10px; |
| 108 | + color: #dc2626; |
| 109 | + margin-top: 1rem; |
85 | 110 | text-align: center; |
| 111 | + font-size: 0.95rem; |
| 112 | + } |
| 113 | + @media (max-width: 480px) { |
| 114 | + .search-container { |
| 115 | + padding: 1.5rem; |
| 116 | + } |
| 117 | + .search-title { |
| 118 | + font-size: 1.25rem; |
| 119 | + } |
86 | 120 | } |
87 | 121 | </style> |
88 | 122 | </head> |
89 | 123 | <body> |
90 | 124 | <div class="search-container"> |
91 | | - <div class="search-title">ACH Routing Number Search</div> |
| 125 | + <div class="search-title">Routing Number Search</div> |
92 | 126 | <div class="search-box"> |
93 | | - <input id="searchInput" type="text" placeholder="Enter routing number..." maxlength="9" /> |
| 127 | + <select id="searchType"> |
| 128 | + <option value="ach">ACH Search</option> |
| 129 | + <option value="wire">Wire Search</option> |
| 130 | + </select> |
| 131 | + <input id="searchInput" type="text" placeholder="Enter 9-digit routing number..." maxlength="9" /> |
94 | 132 | <button id="searchBtn">Search</button> |
95 | 133 | </div> |
96 | 134 | <div id="result"></div> |
97 | 135 | <div id="error" class="error-msg"></div> |
98 | 136 | </div> |
99 | 137 | <script> |
100 | 138 | const input = document.getElementById('searchInput'); |
| 139 | + const searchType = document.getElementById('searchType'); |
101 | 140 | const btn = document.getElementById('searchBtn'); |
102 | 141 | const resultDiv = document.getElementById('result'); |
103 | 142 | const errorDiv = document.getElementById('error'); |
104 | 143 |
|
105 | | - function renderResult(data) { |
106 | | - if (data && data.achParticipants && data.achParticipants.length) { |
| 144 | + function renderResult(data, type) { |
| 145 | + if (type === 'ach' && data?.achParticipants?.length) { |
107 | 146 | const p = data.achParticipants[0]; |
108 | 147 | resultDiv.innerHTML = ` |
109 | 148 | <div class="result-card"> |
|
120 | 159 | <div class="result-row"><span class="result-label">View Code:</span> ${p.viewCode}</div> |
121 | 160 | </div> |
122 | 161 | `; |
123 | | - errorDiv.textContent = ''; |
124 | 162 | return true; |
125 | | - } |
126 | | - return false; |
127 | | - } |
128 | | - |
129 | | - function renderWireResult(data) { |
130 | | - if (data && data.wireParticipants && data.wireParticipants.length) { |
| 163 | + } else if (type === 'wire' && data?.wireParticipants?.length) { |
131 | 164 | const p = data.wireParticipants[0]; |
132 | 165 | resultDiv.innerHTML = ` |
133 | 166 | <div class="result-card"> |
|
141 | 174 | <div class="result-row"><span class="result-label">Date:</span> ${p.date}</div> |
142 | 175 | </div> |
143 | 176 | `; |
144 | | - errorDiv.textContent = ''; |
145 | 177 | return true; |
146 | 178 | } |
147 | 179 | return false; |
148 | 180 | } |
149 | 181 |
|
150 | 182 | async function search() { |
151 | 183 | const routingNumber = input.value.trim(); |
| 184 | + const type = searchType.value; |
152 | 185 | resultDiv.innerHTML = ''; |
153 | 186 | errorDiv.textContent = ''; |
| 187 | + |
154 | 188 | if (!/^\d{9}$/.test(routingNumber)) { |
155 | 189 | errorDiv.textContent = 'Please enter a valid 9-digit routing number.'; |
156 | 190 | return; |
157 | 191 | } |
| 192 | + |
158 | 193 | try { |
159 | | - let res = await fetch(`/fed/ach/search?routingNumber=${routingNumber}`); |
160 | | - if (!res.ok) throw new Error('Network error'); |
161 | | - let data = await res.json(); |
162 | | - if (renderResult(data)) return; |
163 | | - // Try wire search if no ACH participant |
164 | | - res = await fetch(`/fed/wire/search?routingNumber=${routingNumber}`); |
| 194 | + const endpoint = type === 'ach' ? `/fed/ach/search` : `/fed/wire/search`; |
| 195 | + const res = await fetch(`${endpoint}?routingNumber=${routingNumber}`); |
165 | 196 | if (!res.ok) throw new Error('Network error'); |
166 | | - data = await res.json(); |
167 | | - if (renderWireResult(data)) return; |
168 | | - errorDiv.textContent = 'No participant found for this routing number.'; |
| 197 | + const data = await res.json(); |
| 198 | + if (!renderResult(data, type)) { |
| 199 | + errorDiv.textContent = `No ${type.toUpperCase()} participant found for this routing number.`; |
| 200 | + } else { |
| 201 | + errorDiv.textContent = ''; |
| 202 | + } |
169 | 203 | } catch (err) { |
170 | | - resultDiv.innerHTML = ''; |
171 | 204 | errorDiv.textContent = 'Error fetching data. Please try again.'; |
172 | 205 | } |
173 | 206 | } |
174 | 207 |
|
175 | 208 | btn.addEventListener('click', search); |
176 | | - input.addEventListener('keydown', function(e) { |
177 | | - if (e.key === 'Enter') { |
178 | | - search(); |
179 | | - } |
| 209 | + input.addEventListener('keydown', (e) => { |
| 210 | + if (e.key === 'Enter') search(); |
180 | 211 | }); |
181 | 212 | </script> |
182 | 213 | </body> |
|
0 commit comments